c# 多线程实现ping 多线程控制控件 - 图1
    c# 多线程实现ping 多线程控制控件 - 图2


    这个备份器放在项目目录下面,每次使用就双击一下,因为便捷性,就不采用xml等等储存信息,全部在面板内做,这样可以保证一个exe就运行了.
    c# 多线程实现ping 多线程控制控件 - 图3

    我发现运行起来还蛮快的,唯一没有实现的是ping通的电脑如果出现空密码登陆,没有登陆过,还是会有问题…要保证先连接过那台电脑
    如果可以写个大的,例如直接把局域网给弄通了就好了0.0
    代码仅供参照..

    1. using System;
    2. using System.Diagnostics;
    3. using System.IO;
    4. using System.Text;
    5. using System.Threading;
    6. using System.Windows.Forms;
    7. using static JingJingBoxDD.Intranet;
    8. namespace JingJingBoxDD
    9. {
    10. public partial class IntranetBackupDevice : Form
    11. {
    12. #if 宏
    13. private const string _pcNameMostly = "A2";
    14. private const string _proName = "01.饰施图";
    15. #elif
    16. private const string _pcNameMostly = "hzr";
    17. private const string _proName = "01.施工图";
    18. #endif
    19. private string currentPath;
    20. private bool on_off = false;//暂停修改checkedListBox1
    21. /// <summary>
    22. /// 点击计数,用于重新初始化
    23. /// </summary>
    24. private static int CheckedListBox1Counter = 0;
    25. //关闭
    26. private void Button2_Click(object sender, EventArgs e)
    27. {
    28. Close();
    29. }
    30. //作者信息
    31. private void Button3_Click(object sender, EventArgs e)
    32. {
    33. string jj = "www.cnblogs.com/JJBox";
    34. DialogResult dr = MessageBox.Show(
    35. "说明:本程序会在'备份器exe所在位置'进行备份" +
    36. "\n此文件夹前将视为'项目文件夹': " + _proName +
    37. "\n更换网段时候后需要重新ping" +
    38. "\n\n作者:刘启宏 企鹅:540762622" +
    39. "\n博客: " + jj + " ('确定' 进入博客)"
    40. , "惊惊盒子",
    41. MessageBoxButtons.OKCancel
    42. );
    43. if (dr == DialogResult.OK)
    44. {
    45. System.Diagnostics.Process.Start(jj);
    46. }
    47. }
    48. public IntranetBackupDevice()
    49. {
    50. try
    51. {
    52. InitializeComponent();
    53. TopMost = true;//置顶窗体
    54. FormBorderStyle = FormBorderStyle.FixedDialog;//设置边框为不可调节
    55. StartPosition = FormStartPosition.CenterScreen;//在当前屏幕中央
    56. checkedListBox1.HorizontalScrollbar = true;//显示垂直滚动条
    57. checkedListBox1.ScrollAlwaysVisible = true;//显示水平滚动条
    58. checkedListBox1.CheckOnClick = true;//按一下就打钩
    59. textBox3.Text = NetworkSegment;
    60. label6.Text = "默认主机:" + _pcNameMostly;
    61. button1.TabIndex = 0;
    62. //获取exe完整路径,若是网络驱动器,就转换,本地就原本
    63. currentPath = PathTool.GetUNCPath(Process.GetCurrentProcess().MainModule.FileName);
    64. //可以获得不带文件名的路径
    65. currentPath = Path.GetDirectoryName(currentPath);
    66. string fileName = StringTool.PathToFileNameProjectName(currentPath, 1);//获取文件名
    67. if (_proName == fileName)//获取项目名
    68. {
    69. textBox2.Text = StringTool.PathToFileNameProjectName(currentPath, 2);
    70. label7.Text = "警告:无";
    71. }
    72. else
    73. {
    74. label7.Text = string.Format("警告:当前备份器exe不在 {0} 内,将采用以上对话框信息备份.", _proName);
    75. textBox2.Text = fileName;
    76. }
    77. var beifennian = StringTool.GetFlie4Number(textBox2.Text);
    78. if (beifennian == "0")//年份确定
    79. {
    80. DateTime currentTime = DateTime.Now;
    81. textBox4.Text = currentTime.Year.ToString();
    82. }
    83. else
    84. {
    85. textBox4.Text = beifennian;
    86. }
    87. {
    88. //执行死循环修改的
    89. //创建线程 Invoke方法是同步的方法,所以执行过程是有先后顺序的,所以就不会出现那个异常了
    90. Thread newThread = new Thread(new ThreadStart(Runtime))
    91. {
    92. //加上这句话,否则在关闭窗体时会出现如下错误:在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。
    93. IsBackground = true
    94. };
    95. newThread.Start();
    96. }
    97. {
    98. ThreadPool.GetMaxThreads(out int max, out int maxIo);
    99. ThreadPool.GetMinThreads(out int min, out int minIo);
    100. int ipNumbers = ipNumber + 1;
    101. if (max - ipNumbers > 0)
    102. {
    103. max = ipNumbers;
    104. }
    105. if (maxIo - ipNumbers > 0)
    106. {
    107. maxIo = ipNumbers;
    108. }
    109. if (min - ipNumbers < 0)
    110. {
    111. min = ipNumbers;
    112. }
    113. if (minIo - ipNumbers < 0)
    114. {
    115. minIo = ipNumbers;
    116. }
    117. //启动线程池
    118. bool maxbool = ThreadPool.SetMaxThreads(max, maxIo);
    119. bool minbool = ThreadPool.SetMinThreads(min, minIo);
    120. if (maxbool && minbool)
    121. {
    122. Button4_Click(null,null);//开始就执行遍历局域网
    123. label7.Text = string.Format("注明:线程数设置{0},{1},{2},{3}", max, maxIo, min, minIo);
    124. }
    125. else
    126. {
    127. label7.Text = "警告:线程数设置失败";
    128. }
    129. }
    130. }
    131. catch (Exception e)
    132. {
    133. label7.Text = e.Message;
    134. throw e;
    135. }
    136. }
    137. /// <summary>
    138. /// 点击备份
    139. /// </summary>
    140. /// <param name="sender"></param>
    141. /// <param name="e"></param>
    142. private void Button1_Click(object sender, EventArgs e)
    143. {
    144. string dPath = textBox1.Text;
    145. if (dPath != "")
    146. {
    147. if (Directory.Exists(dPath))//防止第二次点击备份
    148. {
    149. label7.ForeColor = System.Drawing.Color.Blue;
    150. label7.Text = "警告:路径已经存在,请更换路径!(是否重复备份了?)";
    151. }
    152. else
    153. {
    154. bool flag = FileTool.Copy(currentPath, dPath);//复制文件
    155. if (flag)
    156. {
    157. label7.ForeColor = System.Drawing.Color.MediumSeaGreen;
    158. label7.Text = "备份成功!";
    159. button5.TabIndex = 0;//设置焦点到打开文件夹
    160. }
    161. else
    162. {
    163. label7.ForeColor = System.Drawing.Color.Blue;
    164. label7.Text = "警告:备份不成功,已执行回滚,请再尝试!";
    165. }
    166. }
    167. }
    168. else
    169. {
    170. label7.ForeColor = System.Drawing.Color.Red;
    171. label7.Text = "警告:备份路径为空!";
    172. }
    173. }
    174. /// <summary>
    175. /// Esc键退出
    176. /// </summary>
    177. /// <param name="sender"></param>
    178. /// <param name="e"></param>
    179. private void Form1_KeyDown(object sender, KeyEventArgs e)
    180. {
    181. if (e.KeyValue == 27) //Esc键
    182. {
    183. Close();
    184. }
    185. }
    186. /// <summary>
    187. /// 窗体将比其内的控件优先获得键盘事件的激活权
    188. /// </summary>
    189. /// <param name="sender"></param>
    190. /// <param name="e"></param>
    191. private void Form1_Load(object sender, EventArgs e)
    192. {
    193. KeyPreview = true;
    194. }
    195. /// <summary>
    196. /// 开始ping 遍历局域网
    197. /// </summary>
    198. /// <param name="sender"></param>
    199. /// <param name="e"></param>
    200. private void Button4_Click(object sender, EventArgs e)
    201. {
    202. //如果用多线程调用的话,会出现多个pingEnt和qiyongEnt值,对加入表造成错误例如多个A2
    203. try
    204. {
    205. //暂停加表,清空表,初始化
    206. on_off = false;
    207. {
    208. pingEnt++;
    209. qiyongEnt++;
    210. NetworkSegment = textBox3.Text;
    211. CheckedListBox1Counter = 0;
    212. for (int i = 0; i < checkedListBox1.Items.Count; i++)
    213. {
    214. checkedListBox1.Items.Clear();
    215. }
    216. Initialization();
    217. }
    218. on_off = true; //继续加入表中
    219. for (int i = 0; i < ipNumber; i++)//生成255个线程
    220. {
    221. ThreadPool.QueueUserWorkItem(new WaitCallback(PingIP), new int[] { i, qiyongEnt });
    222. }
    223. }
    224. catch
    225. {
    226. label7.Text = "警告:RunPing出错";
    227. }
    228. }
    229. /// <summary>
    230. /// 默认选中主机的时候不触发 CheckedListBox1选择事件
    231. /// </summary>
    232. private bool buchufagenggai = true;
    233. /// <summary>
    234. /// 通过委托实现死循环修改面板
    235. /// </summary>
    236. /// https://blog.csdn.net/htiannuo/article/details/52229695
    237. public void Runtime()
    238. {
    239. HostInformation[] conames = new HostInformation[] { };
    240. StringBuilder kongge;
    241. while (true)
    242. {
    243. if (on_off)
    244. {
    245. lock (ComputerNames)
    246. {
    247. conames = ComputerNames.ToArray();
    248. }
    249. if (CheckedListBox1Counter < conames.Length)
    250. {
    251. var conameN = conames[CheckedListBox1Counter];
    252. if (conameN.HostName != "" && conameN.HostIP != "")//锁了就应该不会出现这样的问题了
    253. {
    254. Invoke((EventHandler)delegate
    255. {
    256. //ip可能为名称,ip长度 255.255.255.255 15长+5个空格=20
    257. int bukongge = 20 - conameN.HostName.Length;
    258. kongge = new StringBuilder();
    259. for (int i = 0; i < bukongge; i++)
    260. {
    261. kongge.Append(" ");
    262. }
    263. checkedListBox1.Items.Add(conameN.HostName + kongge + conameN.HostIP + " \t" + conameN.Remarks);
    264. if (conameN.HostName == _pcNameMostly)
    265. {
    266. buchufagenggai = false;
    267. //选择默认主机
    268. checkedListBox1.SetItemCheckState(CheckedListBox1Counter, CheckState.Checked);//打钩
    269. checkedListBox1.SelectedIndex = CheckedListBox1Counter;//焦点项
    270. buchufagenggai = true;
    271. }
    272. });
    273. }
    274. CheckedListBox1Counter++;
    275. //这个不能放在Invoke里面,不然又Form1窗体假死情况
    276. Thread.Sleep(400);
    277. }
    278. }
    279. }
    280. }
    281. /// <summary>
    282. /// 打开文件夹
    283. /// </summary>
    284. /// <param name="sender"></param>
    285. /// <param name="e"></param>
    286. private void Button5_Click(object sender, EventArgs e)
    287. {
    288. if (Directory.Exists(textBox1.Text)) //若路径存在
    289. {
    290. Process.Start("explorer.exe", textBox1.Text);
    291. }
    292. else
    293. {
    294. label7.ForeColor = System.Drawing.Color.Red;
    295. label7.Text = "警告:备份路径为空!请点击备份再点我~";
    296. }
    297. }
    298. /// <summary>
    299. /// 弄成单选
    300. /// </summary>
    301. /// <param name="sender"></param>
    302. /// <param name="e"></param>
    303. private void CheckedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    304. {
    305. if (e.CurrentValue == CheckState.Checked)
    306. {
    307. return;//取消选中就不用进行以下操作
    308. }
    309. for (int i = 0; i < ((CheckedListBox)sender).Items.Count; i++)
    310. {
    311. ((CheckedListBox)sender).SetItemChecked(i, false);//将所有选项设为不选中
    312. }
    313. e.NewValue = CheckState.Checked;//刷新
    314. }
    315. private static string patha = "";
    316. private static string pathTime = "";
    317. /// <summary>
    318. /// CheckedListBox1选择事件
    319. /// </summary>
    320. /// <param name="sender"></param>
    321. /// <param name="e"></param>
    322. private void CheckedListBox1_SelectedIndexChanged(object sender, EventArgs e)
    323. {
    324. // if (buchufagenggai)用了的话会无法直接出现在 textBox1.Text
    325. {
    326. //获取唯一选中项,修改textBox1路径
    327. for (int j = 0; j < checkedListBox1.Items.Count; j++)
    328. {
    329. if (checkedListBox1.GetItemChecked(j))
    330. {
    331. try
    332. {
    333. var conames = ComputerNames.ToArray();
    334. string time = StringTool.GetTimeNoSeconds(out int miao);
    335. string pathb = @"\\" + conames[j].HostName + _SharedFolders;
    336. string pathc = @"\\" + conames[j].HostIP + _SharedFolders;
    337. for (int i = 0; true; i++)
    338. {
    339. bool pb = Directory.Exists(pathb);
    340. if (!pb)
    341. {
    342. pb = Directory.Exists(pathc);
    343. patha = pathc;
    344. }
    345. else
    346. {
    347. patha = pathb;
    348. }
    349. if (pb) //存在一级
    350. {
    351. pathTime = StringTool.GetTimeName(time, ref miao, i);//循环名称不加长
    352. string path = ChangPath(textBox4.Text, textBox2.Text);
    353. if (!Directory.Exists(path)) //存在就循环
    354. {
    355. textBox1.Text = path;
    356. break;
    357. }
    358. }
    359. else
    360. {
    361. DialogResult dr = MessageBox.Show(
    362. patha + "\n\n无法连接,没有开机?不存在机名?没有访问权限?", "惊惊盒子", MessageBoxButtons.OK);
    363. break;
    364. }
    365. }
    366. }
    367. catch
    368. { }
    369. break;
    370. }
    371. }
    372. }
    373. }
    374. private void TextBox2_TextChanged(object sender, EventArgs e)
    375. {
    376. if (patha != "")//防止初始化的时候就更改
    377. {
    378. textBox1.Text = ChangPath(textBox4.Text, textBox2.Text);
    379. }
    380. }
    381. /// <summary>
    382. /// 备份全路径
    383. /// </summary>
    384. /// <param name="beifennian"></param>
    385. /// <param name="project"></param>
    386. /// <returns></returns>
    387. private string ChangPath(string beifennian, string project)
    388. {
    389. return patha + @"\" + beifennian + @"\" + project + @"\" + _proName + @"\" + pathTime;
    390. }
    391. private void Form1_Load(object sender, PreviewKeyDownEventArgs e)
    392. {
    393. }
    394. }
    395. }
    1. using System.Collections.Generic;
    2. using System.Linq;
    3. using System.Net;
    4. using System.Net.NetworkInformation;
    5. using System.Threading;
    6. namespace JingJingBoxDD
    7. {
    8. public partial class Intranet
    9. {
    10. public const string _SharedFoldersA = "中转站";
    11. public const string _SharedFolders = @"\" + _SharedFoldersA;
    12. /// <summary>
    13. /// 网段
    14. /// </summary>
    15. public static string NetworkSegment { get; set; } = "192.168.1";
    16. /// <summary>
    17. /// 按了第几次ping,直到关闭才重置
    18. /// </summary>
    19. public static int pingEnt = 0;
    20. /// <summary>
    21. /// 启用ping的时候计数,直到关闭才重置
    22. /// </summary>
    23. public static int qiyongEnt = 0;
    24. public static bool WaitOne = true;
    25. public static int ipNumber = 256;//ip数
    26. public static List<HostInformation> ComputerNames { get; set; } = new List<HostInformation>();//记录电脑名称和对应的ip,必须初始化,不然无法lock
    27. public static AutoResetEvent pingOver;//线程池结束标记
    28. /// <summary>
    29. /// 初始化
    30. /// </summary>
    31. public static void Initialization()
    32. {
    33. WaitOne = true;
    34. ipNumber = 256;//ip数
    35. pingOver = new AutoResetEvent(false);//线程池结束标记
    36. ComputerNames = new List<HostInformation>();
    37. }
    38. public static void PingIP(object obj)
    39. {
    40. var ints = obj as int[];//0是ip,1是启动点击的位置
    41. string ip = NetworkSegment + "." + ints[0].ToString();
    42. try
    43. {
    44. Ping myPing = new Ping();
    45. PingReply reply = myPing.Send(ip, 1);
    46. if (reply.Status.Equals(IPStatus.Success))//ping通了
    47. {
    48. string hostname = "";
    49. //通过ip获取电脑名称,没有电脑名称会引起错误,造成下面无法递减,必须容错
    50. hostname = Dns.GetHostEntry(ip).HostName;
    51. //当前计数和启用计数要一样才加入,启用是传值的,也是固定的,
    52. //而pingEnt是按了按钮就会改的,存在时间差,造成可以判断.
    53. if (pingEnt == ints[1])
    54. {
    55. if (hostname != null && hostname.Trim() != "")
    56. {
    57. string[] strs = GetNetShareList(hostname);
    58. if (strs.Length == 0)
    59. {
    60. //名称和ip在win10通过空密码时候验证不一样..所以两个都测试一下(如果空密码没有进入过,都会失败
    61. strs = GetNetShareList(ip);
    62. }
    63. if (strs.Length > 0)
    64. {
    65. lock (ComputerNames)
    66. {
    67. if (strs.Contains(_SharedFoldersA))
    68. {
    69. ComputerNames.Add(new HostInformation(hostname.ToUpper(), ip, "有:" + _SharedFoldersA));
    70. }
    71. else
    72. {
    73. ComputerNames.Add(new HostInformation(hostname.ToUpper(), ip, "有共享文件夹,无:" + _SharedFoldersA));
    74. }
    75. }
    76. }
    77. }
    78. else
    79. {
    80. lock (ComputerNames)
    81. {
    82. ComputerNames.Add(new HostInformation(ip, ip, "没有机名但是ping通了"));
    83. }
    84. }
    85. }
    86. }
    87. }
    88. catch
    89. { }
    90. //上面必须容错,实行这里的递减
    91. //线程池计数,用来实现最后一个线程时候通知.
    92. ipNumber--;
    93. //Thread.Sleep(500);
    94. if (ipNumber == 0)
    95. {
    96. pingOver.Set();
    97. }
    98. }
    99. public struct HostInformation
    100. {
    101. public string HostName;
    102. public string HostIP;
    103. public string Remarks;
    104. public HostInformation(string hostname, string hostip, string remarks)
    105. {
    106. HostName = hostname;
    107. HostIP = hostip;
    108. Remarks = remarks;
    109. }
    110. }
    111. /// <summary>
    112. /// 一直等待到找到或者结束
    113. /// </summary>
    114. /// <param name="pcname"></param>
    115. /// <returns></returns>
    116. public static string WhilePing(string pcname)
    117. {
    118. pcname = pcname.ToUpper();
    119. string ip = null;
    120. try
    121. {
    122. while (true)
    123. {
    124. foreach (var item in ComputerNames.ToArray())//防止线程更改了list,必须toarray
    125. {
    126. if (item.HostName == pcname)
    127. {
    128. ip = item.HostIP; //如果找到了ip,就拿出来
    129. break;
    130. }
    131. }
    132. if (WaitOne) //等待过一次就不能再用这个函数
    133. {
    134. WaitOne = false;
    135. pingOver.WaitOne();//等待 pingOver.Set();执行,表示线程池已经终止,如果线程结束,重复等待就会死掉了
    136. }
    137. else
    138. {
    139. break;
    140. }
    141. }
    142. }
    143. catch
    144. { }
    145. return ip;
    146. }
    147. }
    148. }
    1. using System;
    2. using System.Collections;
    3. using System.Runtime.InteropServices;
    4. namespace JingJingBoxDD
    5. {
    6. // https://q.cnblogs.com/q/46971/
    7. public partial class Intranet
    8. {
    9. [StructLayout(LayoutKind.Sequential)]
    10. protected struct SHARE_INFO_1
    11. {
    12. [MarshalAs(UnmanagedType.LPWStr)]
    13. public string shi1_netname;
    14. [MarshalAs(UnmanagedType.U4)]
    15. public uint shi1_type;
    16. [MarshalAs(UnmanagedType.LPWStr)]
    17. public string shi1_remark;
    18. }
    19. [DllImport("Netapi32.dll", CharSet= CharSet.Auto)]// EntryPoint = "NetShareEnum"
    20. protected static extern int NetShareEnum(
    21. [MarshalAs(UnmanagedType.LPWStr)] string servername,
    22. [MarshalAs(UnmanagedType.U4)] uint level,
    23. out IntPtr bufptr,
    24. [MarshalAs(UnmanagedType.U4)] int prefmaxlen,
    25. [MarshalAs(UnmanagedType.U4)] out uint entriesread,
    26. [MarshalAs(UnmanagedType.U4)] out uint totalentries,
    27. [MarshalAs(UnmanagedType.U4)] out uint resume_handle
    28. );
    29. /// <summary>
    30. /// 遍历某台电脑的共享文件
    31. /// </summary>
    32. /// <param name="server"></param>
    33. /// <returns></returns>
    34. public static string[] GetNetShareList(string server)
    35. {
    36. //-1应该是获取所有的share,msdn里面的例子是这么写的,返回0表示成功
    37. if (NetShareEnum(server, 1, out IntPtr buffer, -1, out uint entriesread, out uint totalentries, out uint resume_handle) == 0)
    38. {
    39. int ptr = buffer.ToInt32();
    40. ArrayList alShare = new ArrayList();
    41. for (int i = 0; i < entriesread; i++)
    42. {
    43. SHARE_INFO_1 shareInfo = (SHARE_INFO_1)Marshal.PtrToStructure(new IntPtr(ptr), typeof(SHARE_INFO_1));
    44. if (shareInfo.shi1_type == 0)//Disk drive类型
    45. {
    46. alShare.Add(shareInfo.shi1_netname);
    47. }
    48. ptr += Marshal.SizeOf(shareInfo);//有点类似C代码
    49. }
    50. string[] share = new string[alShare.Count];
    51. for (int i = 0; i < alShare.Count; i++)
    52. {
    53. share[i] = alShare[i].ToString();
    54. }
    55. return share;
    56. }
    57. else
    58. {
    59. return null;
    60. }
    61. }
    62. }
    63. }
    1. using System;
    2. using System.Collections.Generic;
    3. using System.IO;
    4. using System.Runtime.InteropServices;
    5. using System.Windows.Forms;
    6. namespace JingJingBoxDD
    7. {
    8. public static partial class FileTool
    9. {
    10. /// <summary>
    11. /// 复制文件到文件,文件到路径,路径到路径
    12. /// </summary>
    13. /// <param name="sPath"></param>
    14. /// <param name="dPath"></param>
    15. /// <returns></returns>
    16. public static bool Copy(string sPath, string dPath)
    17. {
    18. bool fa =false;
    19. if (sPath.Length - 1 > 0 && sPath.Length - 1 > 0)
    20. {
    21. sPath = sPath.Trim();
    22. while (sPath[sPath.Length - 1] == '\\')
    23. {
    24. sPath = sPath.Substring(0, sPath.Length - 1);
    25. }
    26. dPath = dPath.Trim();
    27. while (dPath[dPath.Length - 1] == '\\')
    28. {
    29. dPath = dPath.Substring(0, dPath.Length - 1);
    30. }
    31. if (File.Exists(sPath) && File.Exists(dPath)) //都是文件
    32. {
    33. fa = CopyFile(sPath, dPath);
    34. }
    35. else if (File.Exists(sPath)) //文件复制到路径
    36. {
    37. fa = CopyFileToPath(sPath, dPath, true);
    38. }
    39. else if (Directory.Exists(sPath)) //目标路径要新建,不能判断
    40. {
    41. fa = CopyDirectory(sPath, dPath);
    42. }
    43. else
    44. {
    45. fa = false;
    46. }
    47. }
    48. return fa;
    49. }
    50. /// <summary>
    51. /// 递归拷贝所有子路径
    52. /// </summary>
    53. /// <param name="sPath">来源</param>
    54. /// <param name="dPath">目标</param>
    55. /// <returns>true成功false不成功</returns>
    56. private static bool CopyDirectory(string sPath, string dPath)
    57. {
    58. bool flag = false;
    59. if (NewFolder(dPath))
    60. {
    61. DirectoryInfo dir = new DirectoryInfo(sPath);//当前路径
    62. flag = CopyFile(dir, dPath);//复制当前路径到目标路径
    63. if (flag)
    64. {
    65. try
    66. {
    67. foreach (var 来源子路径文件夹名 in dir.GetDirectories())//获取所有子路径
    68. {
    69. string 来源子路径的完整路径 = 来源子路径文件夹名.FullName;
    70. string 目标子路径的完整路径 = 来源子路径的完整路径.Replace(sPath, dPath);
    71. if (NewFolder(目标子路径的完整路径))
    72. {
    73. CopyFile(来源子路径文件夹名, 目标子路径的完整路径);
    74. CopyDirectory(来源子路径的完整路径, 目标子路径的完整路径);
    75. }
    76. }
    77. }
    78. catch
    79. {
    80. flag = false;
    81. DelPath(dPath);
    82. }
    83. }
    84. else
    85. {
    86. DelPath(dPath);
    87. }
    88. }
    89. return flag;
    90. }
    91. /// <summary>
    92. /// 拷贝路径下的所有文件到目标路径
    93. /// </summary>
    94. /// <param name="sPath">来源路径</param>
    95. /// <param name="dPath">目标路径</param>
    96. private static bool CopyFile(DirectoryInfo sPath, string dPath)
    97. {
    98. bool flag = true;
    99. try
    100. {
    101. string sourcePath = sPath.FullName;//来源的全路径
    102. FileInfo[] files = sPath.GetFiles();//获取所有文件
    103. foreach (FileInfo file in files)//遍历所有文件
    104. {
    105. file.Attributes = FileAttributes.Normal; //设置为普通文件
    106. string sourceFileFullName = file.FullName;//文件的全路径
    107. string destFileFullName = sourceFileFullName.Replace(sourcePath, dPath);
    108. file.CopyTo(destFileFullName, true);
    109. }
    110. }
    111. catch
    112. {
    113. return false;
    114. }
    115. return flag;
    116. }
    117. /// <summary>
    118. /// 复制大文件
    119. /// </summary>
    120. /// <param name="fromPath">源文件的路径</param>
    121. /// <param name="toPath">文件保存的路径</param>
    122. /// <param name="eachReadLength">每次读取的长度</param>
    123. /// <returns>是否复制成功</returns>
    124. private static bool CopyFile(string fromPath, string toPath)
    125. {
    126. int eachReadLength = 1024 * 1024 * 5;
    127. //将源文件 读取成文件流
    128. FileStream fromFile = new FileStream(fromPath, FileMode.Open, FileAccess.Read);//这样无法读取局域网
    129. //已追加的方式 写入文件流
    130. FileStream toFile = new FileStream(toPath, FileMode.Append, FileAccess.Write);
    131. //实际读取的文件长度
    132. int toCopyLength = 0;
    133. //如果每次读取的长度小于 源文件的长度 分段读取
    134. if (eachReadLength < fromFile.Length)
    135. {
    136. byte[] buffer = new byte[eachReadLength];
    137. long copied = 0;
    138. while (copied <= fromFile.Length - eachReadLength)
    139. {
    140. toCopyLength = fromFile.Read(buffer, 0, eachReadLength);
    141. fromFile.Flush();
    142. toFile.Write(buffer, 0, eachReadLength);
    143. toFile.Flush();
    144. //流的当前位置
    145. toFile.Position = fromFile.Position;
    146. copied += toCopyLength;
    147. }
    148. int left = (int)(fromFile.Length - copied);
    149. toCopyLength = fromFile.Read(buffer, 0, left);
    150. fromFile.Flush();
    151. toFile.Write(buffer, 0, left);
    152. toFile.Flush();
    153. }
    154. else
    155. {
    156. //如果每次拷贝的文件长度大于源文件的长度 则将实际文件长度直接拷贝
    157. byte[] buffer = new byte[fromFile.Length];
    158. fromFile.Read(buffer, 0, buffer.Length);
    159. fromFile.Flush();
    160. toFile.Write(buffer, 0, buffer.Length);
    161. toFile.Flush();
    162. }
    163. fromFile.Close();
    164. toFile.Close();
    165. return true;
    166. }
    167. /// <summary>
    168. /// 复制文件到路径
    169. /// </summary>
    170. /// <param name="file">文件,要完整路径</param>
    171. /// <param name="dPath">目标路径</param>
    172. /// <param name="overwrite">是否覆盖文件</param>
    173. /// <returns></returns>
    174. private static bool CopyFileToPath(string file, string dPath, bool overwrite)
    175. {
    176. bool fa = false;
    177. try
    178. {
    179. if (NewFolder(dPath))
    180. {
    181. string destPath = Path.Combine(dPath, Path.GetFileName(file));
    182. File.Copy(file, destPath, overwrite);
    183. fa = true;
    184. }
    185. }
    186. catch (Exception e)
    187. {
    188. DialogResult dr = MessageBox.Show("复制文件错误!\n" + e.Message, "惊惊盒子", MessageBoxButtons.OKCancel);
    189. }
    190. return fa;
    191. }
    192. #region 删除文件
    193. /// <summary>
    194. /// 删除目录
    195. /// </summary>
    196. /// <param name="pathWhole">全路径</param>
    197. public static bool DelPath(string pathWhole)
    198. {
    199. try
    200. {
    201. pathWhole = StringTool.PathDelLastSlash(pathWhole);
    202. string pathFront = StringTool.PathHigherLevel(pathWhole);
    203. //删除所有子文件
    204. DelDirectory(pathWhole);
    205. //子目录和文件数都是0,才能删除母文件夹
    206. if (Directory.GetDirectories(pathFront).Length == 0 && Directory.GetFiles(pathFront).Length == 0)
    207. {
    208. DirectoryInfo dir = new DirectoryInfo(pathFront)
    209. {
    210. Attributes = FileAttributes.Normal //设置为普通目录
    211. };
    212. dir.Delete(true);//删除文件夹
    213. }
    214. return true;
    215. }
    216. catch
    217. {
    218. return false;
    219. }//回滚出错无需提示,可能是复制不进去
    220. }
    221. /// <summary>
    222. /// 递归删除所有子路径
    223. /// </summary>
    224. /// <param name="sPath">来源</param>
    225. /// <returns>是否成功</returns>
    226. private static bool DelDirectory(string sPath)
    227. {
    228. bool flag = false;//是否成功删除
    229. DirectoryInfo dir = new DirectoryInfo(sPath);//路径
    230. DirectoryInfo[] dirs = dir.GetDirectories(); //获取所有子路径
    231. if (dirs.Length > 0)
    232. {
    233. foreach (var item in dirs)//先处理子路径的文件
    234. {
    235. //子路径如果是文件夹,就嵌套进去
    236. FileAttributes attr = File.GetAttributes(item.FullName);
    237. if (attr == FileAttributes.Directory)
    238. {
    239. DelDirectory(item.FullName);//递归进去删除文件
    240. }
    241. else
    242. {
    243. DirectoryInfo dir2 = new DirectoryInfo(item.FullName)
    244. {
    245. Attributes = FileAttributes.Normal //设置为普通文件
    246. };
    247. dir2.Delete(true);
    248. }
    249. }
    250. flag = true;
    251. }
    252. //最后处理主路径的文件
    253. dir.Attributes = FileAttributes.Normal; //设置为普通文件
    254. dir.Delete(true);//删除文件夹
    255. return flag;
    256. }
    257. /// <summary>
    258. /// 删除文件
    259. /// </summary>
    260. /// <param name="path">文件的路径</param>
    261. /// <returns></returns>
    262. public static bool DelFile(this string path)
    263. {
    264. bool flag = false;
    265. if (File.Exists(path))
    266. {
    267. try
    268. {
    269. FileInfo dir = new FileInfo(path)
    270. {
    271. Attributes = FileAttributes.Normal //设置为普通文件
    272. };
    273. dir.Delete();
    274. flag = true;
    275. }
    276. catch
    277. { }
    278. }
    279. return flag;
    280. }
    281. /// <summary>
    282. /// 重命名文件名字,如果路径还存在就名字+1
    283. /// </summary>
    284. /// <param name="path">文件路径</param>
    285. /// <returns>返回最终的名字,文件不在返回""</returns>
    286. public static string RenameFile(this string path)
    287. {
    288. string str = path;
    289. if (File.Exists(str))
    290. {
    291. int a = 1;
    292. try
    293. {
    294. FileInfo dir = new FileInfo(str)
    295. {
    296. Attributes = FileAttributes.Normal //设置为普通文件
    297. };
    298. string qianzhui = dir.DirectoryName + "\\"; // "D:\\K01.惊惊盒子\\03.用户配置"
    299. while (true)
    300. {
    301. string name = Path.GetFileNameWithoutExtension(path); //返回不带扩展名的文件名
    302. string pathFull = qianzhui + name + a.ToString() + dir.Extension;
    303. if (!File.Exists(pathFull))//如果没有这个文件
    304. {
    305. dir.MoveTo(pathFull);//就重命名这个文件名
    306. str = pathFull;
    307. break;
    308. }
    309. else
    310. {
    311. a++;
    312. }
    313. }
    314. }
    315. catch
    316. { }
    317. }
    318. return str;
    319. }
    320. #endregion
    321. /// <summary>
    322. /// 新建文件夹
    323. /// </summary>
    324. /// <param name="path">路径</param>
    325. /// <returns>成功true,失败false</returns>
    326. public static bool NewFolder(string path)
    327. {
    328. bool flag = false;
    329. try
    330. {
    331. if (!Directory.Exists(path))
    332. {
    333. DirectoryInfo aa = Directory.CreateDirectory(path);//新建文件夹
    334. aa.Attributes = FileAttributes.Normal;//设置文件夹属性为普通
    335. flag = true;
    336. }
    337. }
    338. catch
    339. { }
    340. return flag;
    341. }
    342. /// <summary>
    343. /// 路径中包含某个文件夹,有就返回文件夹路径
    344. /// </summary>
    345. /// <param name="dwgPath">路径</param>
    346. /// <param name="name">文件夹名称</param>
    347. /// <returns>成功返回含有这个文件夹名称的路径,失败返回""</returns>
    348. public static string GetPathIncludeString(string dwgPath, string name)
    349. {
    350. //遍历路径中第几级有"01.饰施图"
    351. char ca = '\\';
    352. string[] dwgPaths = dwgPath.Split(ca);
    353. List<string> st = new List<string>();
    354. for (int i = 0; i < dwgPaths.Length; i++)
    355. {
    356. if (dwgPaths[i] == name)
    357. {
    358. break;
    359. }
    360. else
    361. {
    362. st.Add(dwgPaths[i]);//把前面的路径合并起来
    363. }
    364. }
    365. //如果两个数组相同,表示路径没有"01.饰施图"
    366. string[] stArr = st.ToArray();
    367. string x = "";
    368. if (stArr.Length != dwgPaths.Length)
    369. {
    370. foreach (string item in stArr)
    371. {
    372. x += item + "\\";
    373. }
    374. x += name;
    375. }
    376. return x;
    377. }
    378. /// <summary>
    379. /// 列出本文件夹某个后缀的文件
    380. /// </summary>
    381. /// <param name="path">路径</param>
    382. /// <param name="searchPattern">获取后缀的文件 *.txt</param>
    383. /// <returns></returns>
    384. public static string[] GetThisFolderFiles(string path, string searchPattern)
    385. {
    386. List<string> list = new List<string>();
    387. DirectoryInfo theFolder = new DirectoryInfo(path);
    388. FileInfo[] thefileInfo = theFolder.GetFiles(searchPattern, SearchOption.TopDirectoryOnly);
    389. foreach (FileInfo NextFile in thefileInfo) //遍历文件
    390. {
    391. list.Add(NextFile.FullName);
    392. }
    393. return list.ToArray();
    394. }
    395. #if false
    396. /// <summary>
    397. /// 获取本文件夹及其子文件夹所有后缀的文件
    398. /// </summary>
    399. /// <param name="path">路径</param>
    400. /// <param name="searchPattern">获取后缀的文件 *.txt</param>
    401. /// <returns></returns>
    402. public static string[] GetThisFolderAndSunFiles(string path, string searchPattern)
    403. {
    404. List<string> list = new List<string>();
    405. DirectoryInfo theFolder = new DirectoryInfo(path);
    406. FileInfo[] thefileInfo = theFolder.GetFiles(searchPattern, SearchOption.AllDirectories);
    407. foreach (FileInfo NextFile in thefileInfo) //遍历文件
    408. {
    409. list.Add(NextFile.FullName);
    410. }
    411. return list.ToArray();
    412. }
    413. #endif
    414. /// <summary>
    415. /// 获取路径下所有文件以及子文件夹中文件
    416. /// </summary>
    417. /// <param name="path">全路径根目录</param>
    418. /// <param name="FileList">存放所有文件的全路径</param>
    419. /// <param name="RelativePath"></param>
    420. /// <returns></returns>
    421. public static string[] GetFile(string path, string extension)
    422. {
    423. List<string> pas = new List<string>();
    424. DirectoryInfo dir = new DirectoryInfo(path);
    425. var fil = dir.GetFiles();//获取本文件夹所有文件
    426. foreach (FileInfo f in fil)
    427. {
    428. if (f.Extension.ToUpper() == extension.ToUpper())
    429. {
    430. pas.Add(f.FullName);//保存文件路径到表中
    431. }
    432. }
    433. //获取子文件夹内的文件列表,递归遍历
    434. var dii = dir.GetDirectories();
    435. foreach (DirectoryInfo d in dii)
    436. {
    437. var a = GetFile(d.FullName, extension);//返回数组
    438. foreach (var item in a)
    439. {
    440. pas.Add(item);
    441. }
    442. }
    443. return pas.ToArray();
    444. }
    445. /// <summary>
    446. /// 判断文件是否被程序占用
    447. /// </summary>
    448. /// <param name="fileName">文件路径</param>
    449. /// <returns>true表示正在使用,false没有使用</returns>
    450. public static bool IsFileInUse(string fileName)
    451. {
    452. bool inUse = true;
    453. if (File.Exists(fileName))
    454. {
    455. FileStream fs = null;
    456. try
    457. {
    458. fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
    459. inUse = false;
    460. }
    461. catch
    462. { }
    463. finally
    464. {
    465. if (fs != null)
    466. {
    467. fs.Close();
    468. }
    469. }
    470. return inUse;
    471. }
    472. else
    473. {
    474. return false;//文件不存在,肯定没有被使用
    475. }
    476. }
    477. }
    478. public static partial class FileTool
    479. {
    480. //https://blog.csdn.net/catchme_439/article/details/54616175
    481. private const int FO_COPY = 0x0002;
    482. private const int FOF_ALLOWUNDO = 0x00044;
    483. //显示进度条 0x00044
    484. //不显示一个进度对话框 0x0100 显示进度对话框单不显示进度条 0x0002显示进度条和对话框
    485. private const int FOF_SILENT = 0x0002;//0x0100;
    486. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 0)]
    487. public struct SHFILEOPSTRUCT
    488. {
    489. public IntPtr hwnd;
    490. [MarshalAs(UnmanagedType.U4)]
    491. public int wFunc;
    492. public string pFrom;
    493. public string pTo;
    494. public short fFlags;
    495. [MarshalAs(UnmanagedType.Bool)]
    496. public bool fAnyOperationsAborted;
    497. public IntPtr hNameMappings;
    498. public string lpszProgressTitle;
    499. }
    500. [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    501. private static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);
    502. public static bool ApiCopy(string strSource, string strTarget)
    503. {
    504. SHFILEOPSTRUCT fileop = new SHFILEOPSTRUCT
    505. {
    506. wFunc = FO_COPY,
    507. pFrom = strSource.Trim(),
    508. lpszProgressTitle = "复制大文件",
    509. pTo = strTarget.Trim(),
    510. //fileop.fFlags = FOF_ALLOWUNDO;
    511. fFlags = FOF_SILENT
    512. };
    513. return SHFileOperation(ref fileop) == 0;
    514. }
    515. }
    516. }