c# 多线程实现ping 多线程控制控件

 

 

这个备份器放在项目目录下面,每次使用就双击一下,因为便捷性,就不采用xml等等储存信息,全部在面板内做,这样可以保证一个exe就运行了.

 

我发现运行起来还蛮快的,唯一没有实现的是ping通的电脑如果出现空密码登陆,没有登陆过,还是会有问题...要保证先连接过那台电脑

如果可以写个大的,例如直接把局域网给弄通了就好了0.0

代码仅供参照..

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using static JingJingBoxDD.Intranet;

namespace JingJingBoxDD
{
    public partial class IntranetBackupDevice : Form
    {
#ifprivate const string _pcNameMostly = "A2";
        private const string _proName = "01.饰施图";
#elifprivate const string _pcNameMostly = "hzr";    
        private const string _proName = "01.施工图";
#endif   
        private string currentPath;
        private bool on_off = false;//暂停修改checkedListBox1 

        /// <summary>
        /// 点击计数,用于重新初始化
        /// </summary>
        private static int CheckedListBox1Counter = 0;

        //关闭
        private void Button2_Click(object sender, EventArgs e)
        {
            Close();
        }

        //作者信息
        private void Button3_Click(object sender, EventArgs e)
        {
            string jj = "www.cnblogs.com/JJBox";
            DialogResult dr = MessageBox.Show(
                "说明:本程序会在'备份器exe所在位置'进行备份" +
                 "\n此文件夹前将视为'项目文件夹': " + _proName +
                 "\n更换网段时候后需要重新ping" +
                "\n\n作者:刘启宏    企鹅:540762622" +
                "\n博客: " + jj + " ('确定' 进入博客)"
                , "惊惊盒子",
                MessageBoxButtons.OKCancel
                );
            if (dr == DialogResult.OK)
            {
                System.Diagnostics.Process.Start(jj);
            }
        }

        public IntranetBackupDevice()
        {
            try
            {
                InitializeComponent();

                TopMost = true;//置顶窗体
                FormBorderStyle = FormBorderStyle.FixedDialog;//设置边框为不可调节 
                StartPosition = FormStartPosition.CenterScreen;//在当前屏幕中央 

                checkedListBox1.HorizontalScrollbar = true;//显示垂直滚动条
                checkedListBox1.ScrollAlwaysVisible = true;//显示水平滚动条  
                checkedListBox1.CheckOnClick = true;//按一下就打钩

                textBox3.Text = NetworkSegment;
                label6.Text = "默认主机:" + _pcNameMostly;
                button1.TabIndex = 0;

                //获取exe完整路径,若是网络驱动器,就转换,本地就原本              
                currentPath = PathTool.GetUNCPath(Process.GetCurrentProcess().MainModule.FileName);

                //可以获得不带文件名的路径
                currentPath = Path.GetDirectoryName(currentPath);
                string fileName = StringTool.PathToFileNameProjectName(currentPath, 1);//获取文件名

                if (_proName == fileName)//获取项目名
                {
                    textBox2.Text = StringTool.PathToFileNameProjectName(currentPath, 2);
                    label7.Text = "警告:无";
                }
                else
                {
                    label7.Text = string.Format("警告:当前备份器exe不在 {0} 内,将采用以上对话框信息备份.", _proName);
                    textBox2.Text = fileName;
                }

                var beifennian = StringTool.GetFlie4Number(textBox2.Text);
                if (beifennian == "0")//年份确定 
                {
                    DateTime currentTime = DateTime.Now;
                    textBox4.Text = currentTime.Year.ToString();
                }
                else
                {
                    textBox4.Text = beifennian;
                }
                {
                    //执行死循环修改的
                    //创建线程 Invoke方法是同步的方法,所以执行过程是有先后顺序的,所以就不会出现那个异常了
                    Thread newThread = new Thread(new ThreadStart(Runtime))
                    {
                        //加上这句话,否则在关闭窗体时会出现如下错误:在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。
                        IsBackground = true
                    };
                    newThread.Start();
                }
                {
                    ThreadPool.GetMaxThreads(out int max, out int maxIo);
                    ThreadPool.GetMinThreads(out int min, out int minIo);

                    int ipNumbers = ipNumber + 1;
                    if (max - ipNumbers > 0)
                    {
                        max = ipNumbers;
                    }
                    if (maxIo - ipNumbers > 0)
                    {
                        maxIo = ipNumbers;
                    }
                    if (min - ipNumbers < 0)
                    {
                        min = ipNumbers;
                    }
                    if (minIo - ipNumbers < 0)
                    {
                        minIo = ipNumbers;
                    }
                    //启动线程池 
                    bool maxbool = ThreadPool.SetMaxThreads(max, maxIo);
                    bool minbool = ThreadPool.SetMinThreads(min, minIo);
                    if (maxbool && minbool)
                    {
                        Button4_Click(null,null);//开始就执行遍历局域网
                        label7.Text = string.Format("注明:线程数设置{0},{1},{2},{3}", max, maxIo, min, minIo);
                    }
                    else
                    {
                        label7.Text = "警告:线程数设置失败";
                    }
                }
            }
            catch (Exception e)
            {
                label7.Text = e.Message;
                throw e;
            }
        }

        /// <summary>
        /// 点击备份
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button1_Click(object sender, EventArgs e)
        {
            string dPath = textBox1.Text;
            if (dPath != "")
            {
                if (Directory.Exists(dPath))//防止第二次点击备份
                {
                    label7.ForeColor = System.Drawing.Color.Blue;
                    label7.Text = "警告:路径已经存在,请更换路径!(是否重复备份了?)";
                }
                else
                {
                    bool flag = FileTool.Copy(currentPath, dPath);//复制文件
                    if (flag)
                    {
                        label7.ForeColor = System.Drawing.Color.MediumSeaGreen;
                        label7.Text = "备份成功!";
                        button5.TabIndex = 0;//设置焦点到打开文件夹
                    }
                    else
                    {
                        label7.ForeColor = System.Drawing.Color.Blue;
                        label7.Text = "警告:备份不成功,已执行回滚,请再尝试!";
                    }
                }
            }
            else
            {
                label7.ForeColor = System.Drawing.Color.Red;
                label7.Text = "警告:备份路径为空!";
            }
        }

        /// <summary>
        /// Esc键退出  
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == 27) //Esc键
            {
                Close();
            }
        }

        /// <summary>
        /// 窗体将比其内的控件优先获得键盘事件的激活权
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>  
        private void Form1_Load(object sender, EventArgs e)
        {
            KeyPreview = true;
        }

        /// <summary>
        /// 开始ping 遍历局域网
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button4_Click(object sender, EventArgs e)
        {
            //如果用多线程调用的话,会出现多个pingEnt和qiyongEnt值,对加入表造成错误例如多个A2 
            try
            {
                //暂停加表,清空表,初始化
                on_off = false;
                {
                    pingEnt++;
                    qiyongEnt++;
                    NetworkSegment = textBox3.Text;

                    CheckedListBox1Counter = 0;
                    for (int i = 0; i < checkedListBox1.Items.Count; i++)
                    {
                        checkedListBox1.Items.Clear();
                    }
                    Initialization();
                }
                on_off = true; //继续加入表中 

                for (int i = 0; i < ipNumber; i++)//生成255个线程
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(PingIP), new int[] { i, qiyongEnt });
                }
            }
            catch
            {
                label7.Text = "警告:RunPing出错";
            }
        }

        /// <summary>
        /// 默认选中主机的时候不触发 CheckedListBox1选择事件
        /// </summary>
        private bool buchufagenggai = true;

        /// <summary> 
        /// 通过委托实现死循环修改面板
        /// </summary>
        ///  https://blog.csdn.net/htiannuo/article/details/52229695
        public void Runtime()
        {
            HostInformation[] conames = new HostInformation[] { };
            StringBuilder kongge;

            while (true)
            {
                if (on_off)
                {
                    lock (ComputerNames)
                    {
                        conames = ComputerNames.ToArray();
                    }
                    if (CheckedListBox1Counter < conames.Length)
                    {
                        var conameN = conames[CheckedListBox1Counter];
                        if (conameN.HostName != "" && conameN.HostIP != "")//锁了就应该不会出现这样的问题了  
                        {
                            Invoke((EventHandler)delegate
                            {
                                //ip可能为名称,ip长度 255.255.255.255  15长+5个空格=20 
                                int bukongge = 20 - conameN.HostName.Length;
                                kongge = new StringBuilder();
                                for (int i = 0; i < bukongge; i++)
                                {
                                    kongge.Append(" ");
                                }
                                checkedListBox1.Items.Add(conameN.HostName + kongge + conameN.HostIP + " \t" + conameN.Remarks);

                                if (conameN.HostName == _pcNameMostly)
                                {
                                    buchufagenggai = false;
                                    //选择默认主机
                                    checkedListBox1.SetItemCheckState(CheckedListBox1Counter, CheckState.Checked);//打钩
                                    checkedListBox1.SelectedIndex = CheckedListBox1Counter;//焦点项 
                                    buchufagenggai = true;
                                }
                            });
                        }
                        CheckedListBox1Counter++;
                        //这个不能放在Invoke里面,不然又Form1窗体假死情况
                        Thread.Sleep(400);
                    }
                }
            }
        }

        /// <summary>
        /// 打开文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button5_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(textBox1.Text)) //若路径存在
            {
                Process.Start("explorer.exe", textBox1.Text);
            }
            else
            {
                label7.ForeColor = System.Drawing.Color.Red;
                label7.Text = "警告:备份路径为空!请点击备份再点我~";
            }
        }

        /// <summary>
        /// 弄成单选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (e.CurrentValue == CheckState.Checked)
            {
                return;//取消选中就不用进行以下操作
            }
            for (int i = 0; i < ((CheckedListBox)sender).Items.Count; i++)
            {
                ((CheckedListBox)sender).SetItemChecked(i, false);//将所有选项设为不选中
            }
            e.NewValue = CheckState.Checked;//刷新  
        }

        private static string patha = "";
        private static string pathTime = "";

        /// <summary>
        /// CheckedListBox1选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //  if (buchufagenggai)用了的话会无法直接出现在 textBox1.Text
            {
                //获取唯一选中项,修改textBox1路径  
                for (int j = 0; j < checkedListBox1.Items.Count; j++)
                {
                    if (checkedListBox1.GetItemChecked(j))
                    {
                        try
                        {
                            var conames = ComputerNames.ToArray();
                            string time = StringTool.GetTimeNoSeconds(out int miao);
                            string pathb = @"\\" + conames[j].HostName + _SharedFolders;
                            string pathc = @"\\" + conames[j].HostIP + _SharedFolders;

                            for (int i = 0; true; i++)
                            {
                                bool pb = Directory.Exists(pathb);
                                if (!pb)
                                {
                                    pb = Directory.Exists(pathc);
                                    patha = pathc;
                                }
                                else
                                {
                                    patha = pathb;
                                }
                                if (pb) //存在一级
                                {
                                    pathTime = StringTool.GetTimeName(time, ref miao, i);//循环名称不加长 
                                    string path = ChangPath(textBox4.Text, textBox2.Text);
                                    if (!Directory.Exists(path)) //存在就循环
                                    {
                                        textBox1.Text = path;
                                        break;
                                    }
                                }
                                else
                                {
                                    DialogResult dr = MessageBox.Show(
                                        patha + "\n\n无法连接,没有开机?不存在机名?没有访问权限?", "惊惊盒子", MessageBoxButtons.OK);
                                    break;
                                }
                            }
                        }
                        catch
                        { }
                        break;
                    }
                }
            }
        }

        private void TextBox2_TextChanged(object sender, EventArgs e)
        {
            if (patha != "")//防止初始化的时候就更改
            {
                textBox1.Text = ChangPath(textBox4.Text, textBox2.Text);
            }
        }

        /// <summary>
        /// 备份全路径
        /// </summary>
        /// <param name="beifennian"></param>
        /// <param name="project"></param>
        /// <returns></returns>
        private string ChangPath(string beifennian, string project)
        {
            return patha + @"\" + beifennian + @"\" + project + @"\" + _proName + @"\" + pathTime;
        }

        private void Form1_Load(object sender, PreviewKeyDownEventArgs e)
        {

        }
    }
}
View Code
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;

namespace JingJingBoxDD
{
    public partial class Intranet
    {
        public const string _SharedFoldersA = "中转站";
        public const string _SharedFolders = @"\" + _SharedFoldersA;

        /// <summary>
        /// 网段   
        /// </summary>
        public static string NetworkSegment { get; set; } = "192.168.1";

        /// <summary>
        /// 按了第几次ping,直到关闭才重置
        /// </summary>
        public static int pingEnt = 0;

        /// <summary>
        /// 启用ping的时候计数,直到关闭才重置
        /// </summary>
        public static int qiyongEnt = 0;

        public static bool WaitOne = true;
        public static int ipNumber = 256;//ip数
        public static List<HostInformation> ComputerNames { get; set; } = new List<HostInformation>();//记录电脑名称和对应的ip,必须初始化,不然无法lock
        public static AutoResetEvent pingOver;//线程池结束标记

        /// <summary>
        /// 初始化
        /// </summary>
        public static void Initialization()
        {
            WaitOne = true;
            ipNumber = 256;//ip数 
            pingOver = new AutoResetEvent(false);//线程池结束标记    
            ComputerNames = new List<HostInformation>();
        }

        public static void PingIP(object obj)
        {
            var ints = obj as int[];//0是ip,1是启动点击的位置 
            string ip = NetworkSegment + "." + ints[0].ToString();
            try
            {
                Ping myPing = new Ping();
                PingReply reply = myPing.Send(ip, 1);

                if (reply.Status.Equals(IPStatus.Success))//ping通了
                {
                    string hostname = "";

                    //通过ip获取电脑名称,没有电脑名称会引起错误,造成下面无法递减,必须容错
                    hostname = Dns.GetHostEntry(ip).HostName;

                    //当前计数和启用计数要一样才加入,启用是传值的,也是固定的,
                    //而pingEnt是按了按钮就会改的,存在时间差,造成可以判断. 
                    if (pingEnt == ints[1])
                    {
                        if (hostname != null && hostname.Trim() != "")
                        {
                            string[] strs = GetNetShareList(hostname);
                            if (strs.Length == 0)
                            {
                                //名称和ip在win10通过空密码时候验证不一样..所以两个都测试一下(如果空密码没有进入过,都会失败
                                strs = GetNetShareList(ip);
                            }
                            if (strs.Length > 0)
                            {
                                lock (ComputerNames)
                                {
                                    if (strs.Contains(_SharedFoldersA))
                                    {
                                        ComputerNames.Add(new HostInformation(hostname.ToUpper(), ip, "有:" + _SharedFoldersA));
                                    }
                                    else
                                    {
                                        ComputerNames.Add(new HostInformation(hostname.ToUpper(), ip, "有共享文件夹,无:" + _SharedFoldersA));
                                    }
                                }
                            }
                        }
                        else
                        {
                            lock (ComputerNames)
                            {
                                ComputerNames.Add(new HostInformation(ip, ip, "没有机名但是ping通了"));
                            }
                        }
                    }
                }

            }
            catch
            { }
            //上面必须容错,实行这里的递减
            //线程池计数,用来实现最后一个线程时候通知.
            ipNumber--;
            //Thread.Sleep(500);
            if (ipNumber == 0)
            {
                pingOver.Set();
            }
        }

        public struct HostInformation
        {
            public string HostName;
            public string HostIP;
            public string Remarks;

            public HostInformation(string hostname, string hostip, string remarks)
            {
                HostName = hostname;
                HostIP = hostip;
                Remarks = remarks;
            }
        }

        /// <summary>
        /// 一直等待到找到或者结束
        /// </summary>
        /// <param name="pcname"></param>
        /// <returns></returns>
        public static string WhilePing(string pcname)
        {
            pcname = pcname.ToUpper();
            string ip = null;
            try
            {
                while (true)
                {
                    foreach (var item in ComputerNames.ToArray())//防止线程更改了list,必须toarray
                    {
                        if (item.HostName == pcname)
                        {
                            ip = item.HostIP; //如果找到了ip,就拿出来
                            break;
                        }
                    }
                    if (WaitOne) //等待过一次就不能再用这个函数
                    {
                        WaitOne = false;
                        pingOver.WaitOne();//等待 pingOver.Set();执行,表示线程池已经终止,如果线程结束,重复等待就会死掉了 
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch
            { }
            return ip;
        }
    }
}
View Code
using System;
using System.Collections;
using System.Runtime.InteropServices;


namespace JingJingBoxDD
{   
    // https://q.cnblogs.com/q/46971/   
    public partial class Intranet
    {
        [StructLayout(LayoutKind.Sequential)]
        protected struct SHARE_INFO_1
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi1_netname;
            [MarshalAs(UnmanagedType.U4)]
            public uint shi1_type;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi1_remark;
        }

        [DllImport("Netapi32.dll", CharSet= CharSet.Auto)]// EntryPoint = "NetShareEnum"
        protected static extern int NetShareEnum(
            [MarshalAs(UnmanagedType.LPWStr)] string servername,
            [MarshalAs(UnmanagedType.U4)] uint level,
            out IntPtr bufptr,
            [MarshalAs(UnmanagedType.U4)] int prefmaxlen,
            [MarshalAs(UnmanagedType.U4)] out uint entriesread,
            [MarshalAs(UnmanagedType.U4)] out uint totalentries,
            [MarshalAs(UnmanagedType.U4)] out uint resume_handle
        );

        /// <summary>
        /// 遍历某台电脑的共享文件
        /// </summary>
        /// <param name="server"></param>
        /// <returns></returns>
        public static string[] GetNetShareList(string server)
        {

            //-1应该是获取所有的share,msdn里面的例子是这么写的,返回0表示成功
            if (NetShareEnum(server, 1, out IntPtr buffer, -1, out uint entriesread, out uint totalentries, out uint resume_handle) == 0)
            {
                int ptr = buffer.ToInt32();
                ArrayList alShare = new ArrayList();
                for (int i = 0; i < entriesread; i++)
                {

                    SHARE_INFO_1 shareInfo = (SHARE_INFO_1)Marshal.PtrToStructure(new IntPtr(ptr), typeof(SHARE_INFO_1));
                    if (shareInfo.shi1_type == 0)//Disk drive类型
                    {
                        alShare.Add(shareInfo.shi1_netname);
                    }
                    ptr += Marshal.SizeOf(shareInfo);//有点类似C代码
                }
                string[] share = new string[alShare.Count];
                for (int i = 0; i < alShare.Count; i++)
                {
                    share[i] = alShare[i].ToString();
                }
                return share;
            }
            else
            {
                return null;
            }
        }
    }
}
View Code
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace JingJingBoxDD
{
    public static partial class FileTool
    {

        /// <summary>
        /// 复制文件到文件,文件到路径,路径到路径
        /// </summary>
        /// <param name="sPath"></param>
        /// <param name="dPath"></param>
        /// <returns></returns>
        public static bool Copy(string sPath, string dPath)
        { 
            bool fa =false;
            if (sPath.Length - 1 > 0 && sPath.Length - 1 > 0)
            {
                sPath = sPath.Trim();
                while (sPath[sPath.Length - 1] == '\\')
                {
                    sPath = sPath.Substring(0, sPath.Length - 1);
                }
                dPath = dPath.Trim();
                while (dPath[dPath.Length - 1] == '\\')
                {
                    dPath = dPath.Substring(0, dPath.Length - 1);
                }
                 
                if (File.Exists(sPath) && File.Exists(dPath)) //都是文件
                {
                    fa = CopyFile(sPath, dPath);
                }
                else if (File.Exists(sPath)) //文件复制到路径
                {
                    fa = CopyFileToPath(sPath, dPath, true);
                }
                else if (Directory.Exists(sPath)) //目标路径要新建,不能判断
                {
                    fa = CopyDirectory(sPath, dPath);
                }
                else
                {
                    fa = false;
                } 
            }
            return fa;
        }

        /// <summary>
        /// 递归拷贝所有子路径
        /// </summary>
        /// <param name="sPath">来源</param>
        /// <param name="dPath">目标</param>
        /// <returns>true成功false不成功</returns>    
        private static bool CopyDirectory(string sPath, string dPath)
        {
            bool flag = false;
            if (NewFolder(dPath))
            {
                DirectoryInfo dir = new DirectoryInfo(sPath);//当前路径 
                flag = CopyFile(dir, dPath);//复制当前路径到目标路径
                if (flag)
                {
                    try
                    {
                        foreach (var 来源子路径文件夹名 in dir.GetDirectories())//获取所有子路径
                        {
                            string 来源子路径的完整路径 = 来源子路径文件夹名.FullName;
                            string 目标子路径的完整路径 = 来源子路径的完整路径.Replace(sPath, dPath);
                            if (NewFolder(目标子路径的完整路径))
                            {
                                CopyFile(来源子路径文件夹名, 目标子路径的完整路径);
                                CopyDirectory(来源子路径的完整路径, 目标子路径的完整路径);
                            }
                        }
                    }
                    catch
                    {
                        flag = false;
                        DelPath(dPath);
                    }
                }
                else
                {
                    DelPath(dPath);
                }
            } 
            return flag;
        }

        /// <summary>
        /// 拷贝路径下的所有文件到目标路径
        /// </summary>
        /// <param name="sPath">来源路径</param>
        /// <param name="dPath">目标路径</param>
        private static bool CopyFile(DirectoryInfo sPath, string dPath)
        {
            bool flag = true;
            try
            {
                string sourcePath = sPath.FullName;//来源的全路径
                FileInfo[] files = sPath.GetFiles();//获取所有文件 
                foreach (FileInfo file in files)//遍历所有文件
                {
                    file.Attributes = FileAttributes.Normal; //设置为普通文件
                    string sourceFileFullName = file.FullName;//文件的全路径
                    string destFileFullName = sourceFileFullName.Replace(sourcePath, dPath);
                    file.CopyTo(destFileFullName, true);
                }
            }
            catch
            {
                return false;
            }
            return flag;
        }

        /// <summary>  
        /// 复制大文件  
        /// </summary>  
        /// <param name="fromPath">源文件的路径</param>  
        /// <param name="toPath">文件保存的路径</param>  
        /// <param name="eachReadLength">每次读取的长度</param>  
        /// <returns>是否复制成功</returns>  
        private static bool CopyFile(string fromPath, string toPath)
        {
            int eachReadLength = 1024 * 1024 * 5;

            //将源文件 读取成文件流  
            FileStream fromFile = new FileStream(fromPath, FileMode.Open, FileAccess.Read);//这样无法读取局域网
            //已追加的方式 写入文件流  
            FileStream toFile = new FileStream(toPath, FileMode.Append, FileAccess.Write);
            //实际读取的文件长度  
            int toCopyLength = 0;
            //如果每次读取的长度小于 源文件的长度 分段读取  
            if (eachReadLength < fromFile.Length)
            {
                byte[] buffer = new byte[eachReadLength];
                long copied = 0;
                while (copied <= fromFile.Length - eachReadLength)
                {
                    toCopyLength = fromFile.Read(buffer, 0, eachReadLength);
                    fromFile.Flush();
                    toFile.Write(buffer, 0, eachReadLength);
                    toFile.Flush();
                    //流的当前位置  
                    toFile.Position = fromFile.Position;
                    copied += toCopyLength;
                }
                int left = (int)(fromFile.Length - copied);
                toCopyLength = fromFile.Read(buffer, 0, left);
                fromFile.Flush();
                toFile.Write(buffer, 0, left);
                toFile.Flush();
            }
            else
            {
                //如果每次拷贝的文件长度大于源文件的长度 则将实际文件长度直接拷贝  
                byte[] buffer = new byte[fromFile.Length];
                fromFile.Read(buffer, 0, buffer.Length);
                fromFile.Flush();
                toFile.Write(buffer, 0, buffer.Length);
                toFile.Flush();
            }
            fromFile.Close();
            toFile.Close();
            return true;
        }

        /// <summary>
        /// 复制文件到路径
        /// </summary>
        /// <param name="file">文件,要完整路径</param>
        /// <param name="dPath">目标路径</param>
        /// <param name="overwrite">是否覆盖文件</param>
        /// <returns></returns>
        private static bool CopyFileToPath(string file, string dPath, bool overwrite)
        {
            bool fa = false;
            try
            {
                if (NewFolder(dPath))
                {
                    string destPath = Path.Combine(dPath, Path.GetFileName(file));
                    File.Copy(file, destPath, overwrite);
                    fa = true;
                }
            }
            catch (Exception e)
            {
                DialogResult dr = MessageBox.Show("复制文件错误!\n" + e.Message, "惊惊盒子", MessageBoxButtons.OKCancel);
            }
            return fa;
        }

        #region 删除文件
        /// <summary>
        /// 删除目录
        /// </summary>
        /// <param name="pathWhole">全路径</param>
        public static bool DelPath(string pathWhole)
        {
            try
            {
                pathWhole = StringTool.PathDelLastSlash(pathWhole);
                string pathFront = StringTool.PathHigherLevel(pathWhole);

                //删除所有子文件
                DelDirectory(pathWhole);
                //子目录和文件数都是0,才能删除母文件夹
                if (Directory.GetDirectories(pathFront).Length == 0 && Directory.GetFiles(pathFront).Length == 0)
                {
                    DirectoryInfo dir = new DirectoryInfo(pathFront)
                    {
                        Attributes = FileAttributes.Normal //设置为普通目录 
                    };
                    dir.Delete(true);//删除文件夹
                }
                return true;
            }
            catch
            {
                return false;
            }//回滚出错无需提示,可能是复制不进去
        }

        /// <summary>
        /// 递归删除所有子路径
        /// </summary>
        /// <param name="sPath">来源</param>
        /// <returns>是否成功</returns>    
        private static bool DelDirectory(string sPath)
        {
            bool flag = false;//是否成功删除
            DirectoryInfo dir = new DirectoryInfo(sPath);//路径
            DirectoryInfo[] dirs = dir.GetDirectories(); //获取所有子路径 
            if (dirs.Length > 0)
            {
                foreach (var item in dirs)//先处理子路径的文件
                {
                    //子路径如果是文件夹,就嵌套进去
                    FileAttributes attr = File.GetAttributes(item.FullName);
                    if (attr == FileAttributes.Directory)
                    {
                        DelDirectory(item.FullName);//递归进去删除文件                       
                    }
                    else
                    {
                        DirectoryInfo dir2 = new DirectoryInfo(item.FullName)
                        {
                            Attributes = FileAttributes.Normal //设置为普通文件  
                        };
                        dir2.Delete(true);
                    }
                }
                flag = true;
            }
            //最后处理主路径的文件            
            dir.Attributes = FileAttributes.Normal; //设置为普通文件  
            dir.Delete(true);//删除文件夹
            return flag;
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="path">文件的路径</param>
        /// <returns></returns>
        public static bool DelFile(this string path)
        {
            bool flag = false;
            if (File.Exists(path))
            {
                try
                {
                    FileInfo dir = new FileInfo(path)
                    {
                        Attributes = FileAttributes.Normal //设置为普通文件  
                    };
                    dir.Delete();
                    flag = true;
                }
                catch
                { }
            }
            return flag;
        }

        /// <summary>
        /// 重命名文件名字,如果路径还存在就名字+1
        /// </summary>
        /// <param name="path">文件路径</param>     
        /// <returns>返回最终的名字,文件不在返回""</returns>
        public static string RenameFile(this string path)
        {
            string str = path;
            if (File.Exists(str))
            {
                int a = 1;
                try
                {
                    FileInfo dir = new FileInfo(str)
                    {
                        Attributes = FileAttributes.Normal //设置为普通文件   
                    };
                    string qianzhui = dir.DirectoryName + "\\"; // "D:\\K01.惊惊盒子\\03.用户配置" 
                    while (true)
                    {
                        string name = Path.GetFileNameWithoutExtension(path);     //返回不带扩展名的文件名 

                        string pathFull = qianzhui + name + a.ToString() + dir.Extension;
                        if (!File.Exists(pathFull))//如果没有这个文件
                        {
                            dir.MoveTo(pathFull);//就重命名这个文件名
                            str = pathFull;
                            break;
                        }
                        else
                        {
                            a++;
                        }
                    }
                }
                catch
                { }
            }
            return str;
        }
        #endregion

        /// <summary>
        /// 新建文件夹
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns>成功true,失败false</returns>
        public static bool NewFolder(string path)
        {
            bool flag = false;
            try
            {
                if (!Directory.Exists(path))
                {
                    DirectoryInfo aa = Directory.CreateDirectory(path);//新建文件夹
                    aa.Attributes = FileAttributes.Normal;//设置文件夹属性为普通
                    flag = true;
                }
            }
            catch
            { }
            return flag;
        }

        /// <summary>
        /// 路径中包含某个文件夹,有就返回文件夹路径
        /// </summary>
        /// <param name="dwgPath">路径</param>
        /// <param name="name">文件夹名称</param>
        /// <returns>成功返回含有这个文件夹名称的路径,失败返回""</returns>
        public static string GetPathIncludeString(string dwgPath, string name)
        {
            //遍历路径中第几级有"01.饰施图"
            char ca = '\\';
            string[] dwgPaths = dwgPath.Split(ca);
            List<string> st = new List<string>();
            for (int i = 0; i < dwgPaths.Length; i++)
            {
                if (dwgPaths[i] == name)
                {
                    break;
                }
                else
                {
                    st.Add(dwgPaths[i]);//把前面的路径合并起来
                }
            }
            //如果两个数组相同,表示路径没有"01.饰施图"
            string[] stArr = st.ToArray();
            string x = "";
            if (stArr.Length != dwgPaths.Length)
            {
                foreach (string item in stArr)
                {
                    x += item + "\\";
                }
                x += name;
            }
            return x;
        }

        /// <summary>
        /// 列出本文件夹某个后缀的文件
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="searchPattern">获取后缀的文件 *.txt</param>
        /// <returns></returns>
        public static string[] GetThisFolderFiles(string path, string searchPattern)
        {
            List<string> list = new List<string>();
            DirectoryInfo theFolder = new DirectoryInfo(path);
            FileInfo[] thefileInfo = theFolder.GetFiles(searchPattern, SearchOption.TopDirectoryOnly);
            foreach (FileInfo NextFile in thefileInfo)  //遍历文件
            {
                list.Add(NextFile.FullName);
            }
            return list.ToArray();
        }

#if false
        /// <summary>
        /// 获取本文件夹及其子文件夹所有后缀的文件
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="searchPattern">获取后缀的文件 *.txt</param>
        /// <returns></returns>
        public static string[] GetThisFolderAndSunFiles(string path, string searchPattern)
        {
            List<string> list = new List<string>();
            DirectoryInfo theFolder = new DirectoryInfo(path);
            FileInfo[] thefileInfo = theFolder.GetFiles(searchPattern, SearchOption.AllDirectories);
            foreach (FileInfo NextFile in thefileInfo)  //遍历文件
            {
                list.Add(NextFile.FullName);
            }
            return list.ToArray();
        } 
#endif

        /// <summary>
        /// 获取路径下所有文件以及子文件夹中文件
        /// </summary>
        /// <param name="path">全路径根目录</param>
        /// <param name="FileList">存放所有文件的全路径</param>
        /// <param name="RelativePath"></param>
        /// <returns></returns>
        public static string[] GetFile(string path, string extension)
        {
            List<string> pas = new List<string>();
            DirectoryInfo dir = new DirectoryInfo(path);
            var fil = dir.GetFiles();//获取本文件夹所有文件
            foreach (FileInfo f in fil)
            {
                if (f.Extension.ToUpper() == extension.ToUpper())
                {
                    pas.Add(f.FullName);//保存文件路径到表中
                }
            }
            //获取子文件夹内的文件列表,递归遍历
            var dii = dir.GetDirectories();
            foreach (DirectoryInfo d in dii)
            {
                var a = GetFile(d.FullName, extension);//返回数组
                foreach (var item in a)
                {
                    pas.Add(item);
                }
            }
            return pas.ToArray();
        }

        /// <summary>
        /// 判断文件是否被程序占用
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <returns>true表示正在使用,false没有使用</returns>
        public static bool IsFileInUse(string fileName)
        {
            bool inUse = true;
            if (File.Exists(fileName))
            {
                FileStream fs = null;
                try
                {
                    fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
                    inUse = false;
                }
                catch
                { }
                finally
                {
                    if (fs != null)
                    {
                        fs.Close();
                    }
                }
                return inUse;
            }
            else
            {
                return false;//文件不存在,肯定没有被使用 
            }
        }
    }
    public static partial class FileTool
    {
        //https://blog.csdn.net/catchme_439/article/details/54616175

        private const int FO_COPY = 0x0002;
        private const int FOF_ALLOWUNDO = 0x00044;
        //显示进度条  0x00044 
        //不显示一个进度对话框 0x0100 显示进度对话框单不显示进度条  0x0002显示进度条和对话框  
        private const int FOF_SILENT = 0x0002;//0x0100;
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 0)]
        public struct SHFILEOPSTRUCT
        {
            public IntPtr hwnd;
            [MarshalAs(UnmanagedType.U4)]
            public int wFunc;
            public string pFrom;
            public string pTo;
            public short fFlags;
            [MarshalAs(UnmanagedType.Bool)]
            public bool fAnyOperationsAborted;
            public IntPtr hNameMappings;
            public string lpszProgressTitle;
        }
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        private static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);
        public static bool ApiCopy(string strSource, string strTarget)
        {
            SHFILEOPSTRUCT fileop = new SHFILEOPSTRUCT
            {
                wFunc = FO_COPY,
                pFrom = strSource.Trim(),
                lpszProgressTitle = "复制大文件",
                pTo = strTarget.Trim(),
                //fileop.fFlags = FOF_ALLOWUNDO;  
                fFlags = FOF_SILENT
            };
            return SHFileOperation(ref fileop) == 0;
        }
    }
}
View Code

 

posted @ 2019-02-19 16:35  惊惊  阅读(...)  评论(...编辑  收藏