MainForm.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Windows.Forms;
  10. namespace VberAdmin
  11. {
  12. public partial class FormMain : Form
  13. {
  14. public class CompleteEventArgs : EventArgs
  15. {
  16. public bool IsCompleted { get; set; }
  17. public CompleteEventArgs()
  18. {
  19. IsCompleted = true;
  20. }
  21. }
  22. private List<string> eList = new List<string>();
  23. public FormMain()
  24. {
  25. InitializeComponent();
  26. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  27. }
  28. //public const int WM_SYS_COMMAND = 274;
  29. //public const int SC_MOVE = 61456;
  30. //public const int HT_CAPTION = 2;
  31. [DllImport("user32.dll")]
  32. public static extern bool ReleaseCapture();
  33. [DllImport("user32.dll")]
  34. public static extern bool SendMessage(IntPtr handle, int wMsg, int wParam, int lParam);
  35. private void FormMain_MouseDown(object sender, MouseEventArgs e)
  36. {
  37. ReleaseCapture();
  38. SendMessage(Handle, 274, 61458, 0);
  39. }
  40. private void BtnStart_Click(object sender, EventArgs e)
  41. {
  42. if (btnStart.Text == @"开始")
  43. {
  44. StartMethod();
  45. return;
  46. }
  47. StopMethod();
  48. }
  49. private int MaxNumber = 3;
  50. private void StartMethod()
  51. {
  52. eList = new List<string>();
  53. Arguments arguments = new Arguments
  54. {
  55. OldProjectName = txtOldProjectName.Text.Trim(),
  56. NewProjectName = txtNewProjectName.Text.Trim()
  57. };
  58. if (arguments.OldProjectName.Length > 0 && arguments.OldProjectName.Length < MaxNumber)
  59. {
  60. MessageBox.Show($@"项目名称不能小{MaxNumber}个字符!", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question);
  61. txtOldProjectName.Focus();
  62. return;
  63. }
  64. if (arguments.NewProjectName.Length > 0 && arguments.NewProjectName.Length < MaxNumber)
  65. {
  66. MessageBox.Show($@"新项目名称不能小{MaxNumber}个字符!", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question);
  67. txtNewProjectName.Focus();
  68. return;
  69. }
  70. if (string.IsNullOrEmpty(arguments.NewProjectName))
  71. {
  72. MessageBox.Show(@"请填写新项目名称", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question);
  73. txtNewProjectName.Focus();
  74. return;
  75. }
  76. arguments.RootDir = txtRootDir.Text.Trim();
  77. if (string.IsNullOrWhiteSpace(arguments.RootDir))
  78. {
  79. if (DialogResult.Yes == MessageBox.Show(@"请选择项目路径!", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question))
  80. {
  81. BtnSelect_Click(null, null);
  82. }
  83. return;
  84. }
  85. if (!Directory.Exists(arguments.RootDir))
  86. {
  87. MessageBox.Show(@"请选择正确的项目路径!");
  88. return;
  89. }
  90. panel2.Location = new System.Drawing.Point(Console.Size.Width, panel2.Location.Y);
  91. panel2.Size = new System.Drawing.Size(40, Console.Size.Height);
  92. progressBar.Value = 0;
  93. progressBar.Visible = true;
  94. btnStart.Text = @"进行中……";
  95. backgroundWorker.RunWorkerAsync(arguments);
  96. }
  97. private void StopMethod()
  98. {
  99. if (backgroundWorker.IsBusy)
  100. {
  101. MessageBox.Show(@"取消中...");
  102. backgroundWorker.CancelAsync();
  103. }
  104. }
  105. private void Log(string value)
  106. {
  107. if (Console.InvokeRequired)
  108. {
  109. void Method(string text)
  110. {
  111. Console.AppendText(text);
  112. }
  113. Console.Invoke((Action<string>)Method, value);
  114. return;
  115. }
  116. Console.AppendText(value);
  117. }
  118. private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
  119. {
  120. BackgroundWorker worker = (BackgroundWorker)sender;
  121. if (e.Argument is Arguments arguments)
  122. {
  123. string rootDir = arguments.RootDir;
  124. Stopwatch stopwatch = new Stopwatch();
  125. stopwatch.Start();
  126. RenameAllDir(worker, e, arguments);
  127. stopwatch.Stop();
  128. long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
  129. Log($"================= 目录重命名完成 ================= 花费时间: {elapsedMilliseconds}ms\r\n");
  130. stopwatch.Reset();
  131. stopwatch.Start();
  132. arguments.RootDir = rootDir;
  133. RenameAllFileNameAndContent(worker, e, arguments);
  134. stopwatch.Stop();
  135. Log($"================= 文件名和内容重命名完成 ================= 花费时间: {stopwatch.ElapsedMilliseconds}ms\r\n");
  136. Log($"================= 全部完成 ================= 目录花费时间:{elapsedMilliseconds}ms 文件花费时间: {stopwatch.ElapsedMilliseconds}ms\r\n");
  137. }
  138. }
  139. private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
  140. {
  141. if (e.UserState != null) Log(e.UserState.ToString());
  142. progressBar.PerformStep();
  143. }
  144. private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  145. {
  146. btnStart.Text = @"开始";
  147. if (e.Cancelled)
  148. {
  149. MessageBox.Show(@"任务终止");
  150. return;
  151. }
  152. if (e.Error != null)
  153. {
  154. MessageBox.Show(@"内部错误", e.Error.Message);
  155. throw e.Error;
  156. }
  157. progressBar.Value = progressBar.Maximum;
  158. if (eList.Any())
  159. {
  160. Log("\r\n\r\n\r\n下列文件编码发生转换【UTF-8】:\r\n");
  161. foreach (var file in eList)
  162. {
  163. Log(file + "\r\n");
  164. }
  165. }
  166. if (DialogResult.Yes == MessageBox.Show(@"处理成功完成。 关闭 VberAdmin 重命名工具?", @"提示", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk))
  167. {
  168. BtnClose_Click(null, new CompleteEventArgs());
  169. }
  170. }
  171. private void RenameAllDir(BackgroundWorker worker, DoWorkEventArgs e, Arguments arguments)
  172. {
  173. string[] array = Directory.GetDirectories(arguments.RootDir);
  174. int percentProgress = 0;
  175. foreach (var text in array)
  176. {
  177. if (worker.CancellationPending)
  178. {
  179. e.Cancel = true;
  180. return;
  181. }
  182. arguments.RootDir = text;
  183. RenameAllDir(worker, e, arguments);
  184. DirectoryInfo directoryInfo = new DirectoryInfo(text);
  185. if (directoryInfo.Name.Contains(arguments.OldProjectName))
  186. {
  187. string text2 = directoryInfo.Name.Replace(arguments.OldProjectName, arguments.NewProjectName);
  188. string text3 = Path.Combine(directoryInfo.Parent?.FullName ?? "", text2);
  189. if (directoryInfo.FullName != text3)
  190. {
  191. worker.ReportProgress(percentProgress, directoryInfo.FullName + "\r\n=>\r\n" + text3 + "\r\n\r\n");
  192. directoryInfo.MoveTo(text3);
  193. }
  194. }
  195. }
  196. }
  197. private void RenameAllFileNameAndContent(BackgroundWorker worker, DoWorkEventArgs e, Arguments arguments)
  198. {
  199. List<FileInfo> fileInfos = (
  200. from m in new DirectoryInfo(arguments.RootDir).GetFiles()
  201. where arguments.filter.Contains(m.Extension)
  202. select m).ToList();
  203. int percentProgress = 0;
  204. foreach (FileInfo current in fileInfos)
  205. {
  206. if (worker.CancellationPending)
  207. {
  208. e.Cancel = true;
  209. break;
  210. }
  211. var targetEncoding = Encoding.UTF8;
  212. string text = File.ReadAllText(current.FullName, targetEncoding);
  213. using (FileStream fs = new FileStream(current.FullName, FileMode.Open, FileAccess.Read))
  214. {
  215. byte[] bytes = new byte[fs.Length];
  216. fs.Read(bytes, 0, (int)fs.Length);
  217. Encoding encoding = GetType(bytes);
  218. if (!Equals(encoding, targetEncoding))
  219. {
  220. eList.Add(current.FullName);
  221. text = encoding.GetString(bytes);
  222. }
  223. }
  224. text = text.Replace(arguments.OldProjectName, arguments.NewProjectName);
  225. if (current.Name.Contains(arguments.OldProjectName))
  226. {
  227. string text2 = current.Name.Replace(arguments.OldProjectName, arguments.NewProjectName);
  228. if (current.DirectoryName != null)
  229. {
  230. string text3 = Path.Combine(current.DirectoryName, text2);
  231. if (text3 != current.FullName)
  232. {
  233. worker.ReportProgress(percentProgress, string.Concat("\r\n", current.FullName, "\r\n=>\r\n", text3, "\r\n\r\n"));
  234. File.Delete(current.FullName);
  235. }
  236. File.WriteAllText(text3, text, targetEncoding);
  237. }
  238. }
  239. else
  240. {
  241. File.WriteAllText(current.FullName, text, targetEncoding);
  242. }
  243. worker.ReportProgress(percentProgress, current.Name + " => 完成 \r\n");
  244. }
  245. string[] directories = Directory.GetDirectories(arguments.RootDir);
  246. foreach (var rootDir in directories)
  247. {
  248. if (worker.CancellationPending)
  249. {
  250. e.Cancel = true;
  251. return;
  252. }
  253. arguments.RootDir = rootDir;
  254. RenameAllFileNameAndContent(worker, e, arguments);
  255. }
  256. }
  257. private void BtnSelect_Click(object sender, EventArgs e)
  258. {
  259. FolderBrowserDialog dialog = new FolderBrowserDialog
  260. {
  261. Description = @"请选择ABP项目所在的文件夹(VberAdmin_V4+)",
  262. UseDescriptionForTitle = true,
  263. };
  264. if (!string.IsNullOrWhiteSpace(txtRootDir.Text))
  265. {
  266. dialog.SelectedPath = txtRootDir.Text;
  267. }
  268. if (dialog.ShowDialog() == DialogResult.OK)
  269. {
  270. if (string.IsNullOrEmpty(dialog.SelectedPath))
  271. {
  272. MessageBox.Show(this, @"文件夹路径不能为空", @"提示");
  273. return;
  274. }
  275. txtRootDir.Text = dialog.SelectedPath;
  276. }
  277. }
  278. private void BtnClose_Click(object sender, EventArgs e)
  279. {
  280. if (!string.IsNullOrWhiteSpace(txtFilter.Text))
  281. {
  282. Settings.Default.setFilter = txtFilter.Text.Trim();
  283. }
  284. if (!string.IsNullOrWhiteSpace(txtOldProjectName.Text))
  285. {
  286. Settings.Default.setOldProjectName = txtOldProjectName.Text.Trim();
  287. }
  288. if (!string.IsNullOrWhiteSpace(txtRootDir.Text))
  289. {
  290. Settings.Default.setRootDir = txtRootDir.Text.Trim();
  291. }
  292. //if (e is CompleteEventArgs)
  293. //{
  294. // Settings.Default.setOldProjectName = txtNewProjectName.Text.Trim();
  295. //}
  296. Settings.Default.Save();
  297. Environment.Exit(0);
  298. }
  299. private void FormMain_Load(object sender, EventArgs e)
  300. {
  301. btnStart.Text = @"开始";
  302. if (!string.IsNullOrWhiteSpace(Settings.Default.setFilter))
  303. {
  304. txtFilter.Text = Settings.Default.setFilter.Trim();
  305. }
  306. if (!string.IsNullOrWhiteSpace(Settings.Default.setOldProjectName))
  307. {
  308. txtOldProjectName.Text = Settings.Default.setOldProjectName.Trim();
  309. }
  310. if (!string.IsNullOrWhiteSpace(Settings.Default.setNewProjectName))
  311. {
  312. txtNewProjectName.Text = Settings.Default.setNewProjectName.Trim();
  313. }
  314. if (!string.IsNullOrWhiteSpace(Settings.Default.setRootDir))
  315. {
  316. txtRootDir.Text = Settings.Default.setRootDir.Trim();
  317. }
  318. }
  319. private void BtnReset_Click(object sender, EventArgs e)
  320. {
  321. txtFilter.Text = @".cs,.cshtml,.csproj,.sln,.xml,.config,.DotSettings,.json,.xaml,.txt,.html,.gitignore,.ps1,.md,.plist";
  322. }
  323. private void lbOriginalProjectName_Click(object sender, EventArgs e)
  324. {
  325. txtOldProjectName.Text = @"VberAdmin";
  326. }
  327. private void lbProjectPath_Click(object sender, EventArgs e)
  328. {
  329. txtRootDir.Text = "";
  330. }
  331. private void lbNewProjectName_Click(object sender, EventArgs e)
  332. {
  333. txtNewProjectName.Text = "";
  334. }
  335. public static Encoding GetType(string fileName)
  336. {
  337. using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
  338. {
  339. Encoding r = GetType(fs);
  340. return r;
  341. }
  342. }
  343. public string EncodingChange(string str, Encoding originalEncoding = null, Encoding targetEncoding = null)
  344. {
  345. targetEncoding = targetEncoding ?? Encoding.GetEncoding("UTF-8");
  346. originalEncoding = originalEncoding ?? Encoding.GetEncoding("GB2312");
  347. byte[] originalBytes = originalEncoding.GetBytes(str);
  348. originalBytes = Encoding.Convert(originalEncoding, targetEncoding, originalBytes);
  349. return targetEncoding.GetString(originalBytes);
  350. }
  351. public static Encoding GetType(FileStream fs, Encoding defaultEncoding = null)
  352. {
  353. //byte[] Unicode = { 0xFF, 0xFE, 0x41 };
  354. //byte[] UnicodeBIG = { 0xFE, 0xFF, 0x00 };
  355. //byte[] UTF8 = { 0xEF, 0xBB, 0xBF }; //带BOM
  356. var encoding = defaultEncoding ?? Encoding.GetEncoding("gb2312");
  357. //var r = new BinaryReader(fs, Encoding.Default);
  358. //int.TryParse(fs.Length.ToString(), out var i);
  359. //var bytes = r.ReadBytes(i);
  360. byte[] bytes = new byte[fs.Length];
  361. fs.Read(bytes, 0, (int)fs.Length);
  362. if (IsUTF8Bytes(bytes) || bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
  363. {
  364. encoding = Encoding.UTF8;
  365. }
  366. else if (bytes[0] == 0xFE && bytes[1] == 0xFF && bytes[2] == 0x00)
  367. {
  368. encoding = Encoding.BigEndianUnicode;
  369. }
  370. else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0x41)
  371. {
  372. encoding = Encoding.Unicode;
  373. }
  374. //r.Close();
  375. return encoding;
  376. }
  377. public static Encoding GetType(byte[] bytes, Encoding defaultEncoding = null)
  378. {
  379. var encoding = defaultEncoding ?? Encoding.GetEncoding("gb2312");
  380. if (IsUTF8Bytes(bytes) || bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
  381. {
  382. encoding = Encoding.UTF8;
  383. }
  384. else if (bytes[0] == 0xFE && bytes[1] == 0xFF && bytes[2] == 0x00)
  385. {
  386. encoding = Encoding.BigEndianUnicode;
  387. }
  388. else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0x41)
  389. {
  390. encoding = Encoding.Unicode;
  391. }
  392. return encoding;
  393. }
  394. private static bool IsUTF8Bytes(byte[] data)
  395. {
  396. var charByteCounter = 1; //计算当前正分析的字符应还有的字节数
  397. for (var i = data.Length - 1; i >= 0; i--)
  398. {
  399. var curByte = data[i]; //当前分析的字节.
  400. if (charByteCounter == 1)
  401. {
  402. if (curByte >= 0x80)
  403. {
  404. //判断当前
  405. while (((curByte <<= 1) & 0x80) != 0)
  406. {
  407. charByteCounter++;
  408. }
  409. //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X
  410. if (charByteCounter == 1 || charByteCounter > 6)
  411. {
  412. return false;
  413. }
  414. }
  415. }
  416. else
  417. {
  418. //若是UTF-8 此时第一位必须为1
  419. if ((curByte & 0xC0) != 0x80)
  420. {
  421. return false;
  422. }
  423. charByteCounter--;
  424. }
  425. }
  426. if (charByteCounter > 1)
  427. {
  428. throw new Exception("非预期的byte格式");
  429. }
  430. return true;
  431. }
  432. }
  433. }