using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace VberAdmin { public partial class FormMain : Form { public class CompleteEventArgs : EventArgs { public bool IsCompleted { get; set; } public CompleteEventArgs() { IsCompleted = true; } } private List eList = new List(); public FormMain() { InitializeComponent(); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); } //public const int WM_SYS_COMMAND = 274; //public const int SC_MOVE = 61456; //public const int HT_CAPTION = 2; [DllImport("user32.dll")] public static extern bool ReleaseCapture(); [DllImport("user32.dll")] public static extern bool SendMessage(IntPtr handle, int wMsg, int wParam, int lParam); private void FormMain_MouseDown(object sender, MouseEventArgs e) { ReleaseCapture(); SendMessage(Handle, 274, 61458, 0); } private void BtnStart_Click(object sender, EventArgs e) { if (btnStart.Text == @"开始") { StartMethod(); return; } StopMethod(); } private int MaxNumber = 3; private void StartMethod() { eList = new List(); Arguments arguments = new Arguments { OldProjectName = txtOldProjectName.Text.Trim(), NewProjectName = txtNewProjectName.Text.Trim() }; if (arguments.OldProjectName.Length > 0 && arguments.OldProjectName.Length < MaxNumber) { MessageBox.Show($@"项目名称不能小{MaxNumber}个字符!", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question); txtOldProjectName.Focus(); return; } if (arguments.NewProjectName.Length > 0 && arguments.NewProjectName.Length < MaxNumber) { MessageBox.Show($@"新项目名称不能小{MaxNumber}个字符!", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question); txtNewProjectName.Focus(); return; } if (string.IsNullOrEmpty(arguments.NewProjectName)) { MessageBox.Show(@"请填写新项目名称", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question); txtNewProjectName.Focus(); return; } arguments.RootDir = txtRootDir.Text.Trim(); if (string.IsNullOrWhiteSpace(arguments.RootDir)) { if (DialogResult.Yes == MessageBox.Show(@"请选择项目路径!", @"提示", MessageBoxButtons.OK, MessageBoxIcon.Question)) { BtnSelect_Click(null, null); } return; } if (!Directory.Exists(arguments.RootDir)) { MessageBox.Show(@"请选择正确的项目路径!"); return; } panel2.Location = new System.Drawing.Point(Console.Size.Width, panel2.Location.Y); panel2.Size = new System.Drawing.Size(40, Console.Size.Height); progressBar.Value = 0; progressBar.Visible = true; btnStart.Text = @"进行中……"; backgroundWorker.RunWorkerAsync(arguments); } private void StopMethod() { if (backgroundWorker.IsBusy) { MessageBox.Show(@"取消中..."); backgroundWorker.CancelAsync(); } } private void Log(string value) { if (Console.InvokeRequired) { void Method(string text) { Console.AppendText(text); } Console.Invoke((Action)Method, value); return; } Console.AppendText(value); } private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = (BackgroundWorker)sender; if (e.Argument is Arguments arguments) { string rootDir = arguments.RootDir; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); RenameAllDir(worker, e, arguments); stopwatch.Stop(); long elapsedMilliseconds = stopwatch.ElapsedMilliseconds; Log($"================= 目录重命名完成 ================= 花费时间: {elapsedMilliseconds}ms\r\n"); stopwatch.Reset(); stopwatch.Start(); arguments.RootDir = rootDir; RenameAllFileNameAndContent(worker, e, arguments); stopwatch.Stop(); Log($"================= 文件名和内容重命名完成 ================= 花费时间: {stopwatch.ElapsedMilliseconds}ms\r\n"); Log($"================= 全部完成 ================= 目录花费时间:{elapsedMilliseconds}ms 文件花费时间: {stopwatch.ElapsedMilliseconds}ms\r\n"); } } private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (e.UserState != null) Log(e.UserState.ToString()); progressBar.PerformStep(); } private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { btnStart.Text = @"开始"; if (e.Cancelled) { MessageBox.Show(@"任务终止"); return; } if (e.Error != null) { MessageBox.Show(@"内部错误", e.Error.Message); throw e.Error; } progressBar.Value = progressBar.Maximum; if (eList.Any()) { Log("\r\n\r\n\r\n下列文件编码发生转换【UTF-8】:\r\n"); foreach (var file in eList) { Log(file + "\r\n"); } } if (DialogResult.Yes == MessageBox.Show(@"处理成功完成。 关闭 VberAdmin 重命名工具?", @"提示", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk)) { BtnClose_Click(null, new CompleteEventArgs()); } } private void RenameAllDir(BackgroundWorker worker, DoWorkEventArgs e, Arguments arguments) { string[] array = Directory.GetDirectories(arguments.RootDir); int percentProgress = 0; foreach (var text in array) { if (worker.CancellationPending) { e.Cancel = true; return; } arguments.RootDir = text; RenameAllDir(worker, e, arguments); DirectoryInfo directoryInfo = new DirectoryInfo(text); if (directoryInfo.Name.Contains(arguments.OldProjectName)) { string text2 = directoryInfo.Name.Replace(arguments.OldProjectName, arguments.NewProjectName); string text3 = Path.Combine(directoryInfo.Parent?.FullName ?? "", text2); if (directoryInfo.FullName != text3) { worker.ReportProgress(percentProgress, directoryInfo.FullName + "\r\n=>\r\n" + text3 + "\r\n\r\n"); directoryInfo.MoveTo(text3); } } } } private void RenameAllFileNameAndContent(BackgroundWorker worker, DoWorkEventArgs e, Arguments arguments) { List fileInfos = ( from m in new DirectoryInfo(arguments.RootDir).GetFiles() where arguments.filter.Contains(m.Extension) select m).ToList(); int percentProgress = 0; foreach (FileInfo current in fileInfos) { if (worker.CancellationPending) { e.Cancel = true; break; } var targetEncoding = Encoding.UTF8; string text = File.ReadAllText(current.FullName, targetEncoding); using (FileStream fs = new FileStream(current.FullName, FileMode.Open, FileAccess.Read)) { byte[] bytes = new byte[fs.Length]; fs.Read(bytes, 0, (int)fs.Length); Encoding encoding = GetType(bytes); if (!Equals(encoding, targetEncoding)) { eList.Add(current.FullName); text = encoding.GetString(bytes); } } text = text.Replace(arguments.OldProjectName, arguments.NewProjectName); if (current.Name.Contains(arguments.OldProjectName)) { string text2 = current.Name.Replace(arguments.OldProjectName, arguments.NewProjectName); if (current.DirectoryName != null) { string text3 = Path.Combine(current.DirectoryName, text2); if (text3 != current.FullName) { worker.ReportProgress(percentProgress, string.Concat("\r\n", current.FullName, "\r\n=>\r\n", text3, "\r\n\r\n")); File.Delete(current.FullName); } File.WriteAllText(text3, text, targetEncoding); } } else { File.WriteAllText(current.FullName, text, targetEncoding); } worker.ReportProgress(percentProgress, current.Name + " => 完成 \r\n"); } string[] directories = Directory.GetDirectories(arguments.RootDir); foreach (var rootDir in directories) { if (worker.CancellationPending) { e.Cancel = true; return; } arguments.RootDir = rootDir; RenameAllFileNameAndContent(worker, e, arguments); } } private void BtnSelect_Click(object sender, EventArgs e) { FolderBrowserDialog dialog = new FolderBrowserDialog { Description = @"请选择ABP项目所在的文件夹(VberAdmin_V4+)", UseDescriptionForTitle = true, }; if (!string.IsNullOrWhiteSpace(txtRootDir.Text)) { dialog.SelectedPath = txtRootDir.Text; } if (dialog.ShowDialog() == DialogResult.OK) { if (string.IsNullOrEmpty(dialog.SelectedPath)) { MessageBox.Show(this, @"文件夹路径不能为空", @"提示"); return; } txtRootDir.Text = dialog.SelectedPath; } } private void BtnClose_Click(object sender, EventArgs e) { if (!string.IsNullOrWhiteSpace(txtFilter.Text)) { Settings.Default.setFilter = txtFilter.Text.Trim(); } if (!string.IsNullOrWhiteSpace(txtOldProjectName.Text)) { Settings.Default.setOldProjectName = txtOldProjectName.Text.Trim(); } if (!string.IsNullOrWhiteSpace(txtRootDir.Text)) { Settings.Default.setRootDir = txtRootDir.Text.Trim(); } //if (e is CompleteEventArgs) //{ // Settings.Default.setOldProjectName = txtNewProjectName.Text.Trim(); //} Settings.Default.Save(); Environment.Exit(0); } private void FormMain_Load(object sender, EventArgs e) { btnStart.Text = @"开始"; if (!string.IsNullOrWhiteSpace(Settings.Default.setFilter)) { txtFilter.Text = Settings.Default.setFilter.Trim(); } if (!string.IsNullOrWhiteSpace(Settings.Default.setOldProjectName)) { txtOldProjectName.Text = Settings.Default.setOldProjectName.Trim(); } if (!string.IsNullOrWhiteSpace(Settings.Default.setNewProjectName)) { txtNewProjectName.Text = Settings.Default.setNewProjectName.Trim(); } if (!string.IsNullOrWhiteSpace(Settings.Default.setRootDir)) { txtRootDir.Text = Settings.Default.setRootDir.Trim(); } } private void BtnReset_Click(object sender, EventArgs e) { txtFilter.Text = @".cs,.cshtml,.csproj,.sln,.xml,.config,.DotSettings,.json,.xaml,.txt,.html,.gitignore,.ps1,.md,.plist"; } private void lbOriginalProjectName_Click(object sender, EventArgs e) { txtOldProjectName.Text = @"VberAdmin"; } private void lbProjectPath_Click(object sender, EventArgs e) { txtRootDir.Text = ""; } private void lbNewProjectName_Click(object sender, EventArgs e) { txtNewProjectName.Text = ""; } public static Encoding GetType(string fileName) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { Encoding r = GetType(fs); return r; } } public string EncodingChange(string str, Encoding originalEncoding = null, Encoding targetEncoding = null) { targetEncoding = targetEncoding ?? Encoding.GetEncoding("UTF-8"); originalEncoding = originalEncoding ?? Encoding.GetEncoding("GB2312"); byte[] originalBytes = originalEncoding.GetBytes(str); originalBytes = Encoding.Convert(originalEncoding, targetEncoding, originalBytes); return targetEncoding.GetString(originalBytes); } public static Encoding GetType(FileStream fs, Encoding defaultEncoding = null) { //byte[] Unicode = { 0xFF, 0xFE, 0x41 }; //byte[] UnicodeBIG = { 0xFE, 0xFF, 0x00 }; //byte[] UTF8 = { 0xEF, 0xBB, 0xBF }; //带BOM var encoding = defaultEncoding ?? Encoding.GetEncoding("gb2312"); //var r = new BinaryReader(fs, Encoding.Default); //int.TryParse(fs.Length.ToString(), out var i); //var bytes = r.ReadBytes(i); byte[] bytes = new byte[fs.Length]; fs.Read(bytes, 0, (int)fs.Length); if (IsUTF8Bytes(bytes) || bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { encoding = Encoding.UTF8; } else if (bytes[0] == 0xFE && bytes[1] == 0xFF && bytes[2] == 0x00) { encoding = Encoding.BigEndianUnicode; } else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0x41) { encoding = Encoding.Unicode; } //r.Close(); return encoding; } public static Encoding GetType(byte[] bytes, Encoding defaultEncoding = null) { var encoding = defaultEncoding ?? Encoding.GetEncoding("gb2312"); if (IsUTF8Bytes(bytes) || bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { encoding = Encoding.UTF8; } else if (bytes[0] == 0xFE && bytes[1] == 0xFF && bytes[2] == 0x00) { encoding = Encoding.BigEndianUnicode; } else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0x41) { encoding = Encoding.Unicode; } return encoding; } private static bool IsUTF8Bytes(byte[] data) { var charByteCounter = 1; //计算当前正分析的字符应还有的字节数 for (var i = data.Length - 1; i >= 0; i--) { var curByte = data[i]; //当前分析的字节. if (charByteCounter == 1) { if (curByte >= 0x80) { //判断当前 while (((curByte <<= 1) & 0x80) != 0) { charByteCounter++; } //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X if (charByteCounter == 1 || charByteCounter > 6) { return false; } } } else { //若是UTF-8 此时第一位必须为1 if ((curByte & 0xC0) != 0x80) { return false; } charByteCounter--; } } if (charByteCounter > 1) { throw new Exception("非预期的byte格式"); } return true; } } }