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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM