欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁

最编程 2024-02-23 13:38:10
...
// https://github.com/dotnet-campus/dotnetcampus.DotNETBuildSDK/tree/master/PublishFolderCleaner using System.Diagnostics; using System.Text; // 名称, 不用写 .exe var exeName = "AbpDemo"; // 目录 var publishFolder = "D:\\Work\\CSharpProject\\AbpDemo\\AbpDemo\\bin\\Debug\\net8.0"; const string libFolderName = "lib"; var libFolder = Path.GetFullPath(Path.Combine(publishFolder, libFolderName)); var tempFolder = Path.GetFullPath(Path.Combine(publishFolder, @"..", Path.GetRandomFileName())); Directory.Move(publishFolder, tempFolder); Directory.CreateDirectory(publishFolder); Directory.Move(tempFolder, libFolder); var appHostFilePath = Path.Combine(libFolder, exeName + ".exe"); var newAppHostFilePath = Path.Combine(publishFolder, exeName + ".exe"); File.Move(appHostFilePath, newAppHostFilePath); Patch(newAppHostFilePath, Path.Combine("lib", exeName + ".dll")); /// <summary> /// 这里有 1024 个 byte 空间用来决定加载路径 /// 详细请看 dotnet runtime\src\installer\corehost\corehost.cpp 的注释 /// </summary> const int MaxPathBytes = 1024; int Patch(string appHostExe, string newPath) { try { var origPath = Path.GetFileName(ChangeExecutableExtension(appHostExe)); if (!File.Exists(appHostExe)) { Console.WriteLine($"AppHost '{appHostExe}' does not exist"); return 1; } if (origPath == string.Empty) { Console.WriteLine("Original path is empty"); return 1; } var origPathBytes = Encoding.UTF8.GetBytes(origPath + "\0"); Debug.Assert(origPathBytes.Length > 0); var newPathBytes = Encoding.UTF8.GetBytes(newPath + "\0"); if (origPathBytes.Length > MaxPathBytes) { Console.WriteLine($"Original path is too long"); return 1; } if (newPathBytes.Length > MaxPathBytes) { Console.WriteLine($"New path is too long"); return 1; } var appHostExeBytes = File.ReadAllBytes(appHostExe); int offset = GetOffset(appHostExeBytes, origPathBytes); if (offset < 0) { Console.WriteLine($"Could not find original path '{origPath}'"); return 1; } if (offset + newPathBytes.Length > appHostExeBytes.Length) { Console.WriteLine($"New path is too long: {newPath}"); return 1; } for (int i = 0; i < newPathBytes.Length; i++) appHostExeBytes[offset + i] = newPathBytes[i]; File.WriteAllBytes(appHostExe, appHostExeBytes); return 0; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return 1; } } string ChangeExecutableExtension(string apphostExe) => // Windows apphosts have an .exe extension. Don't call Path.ChangeExtension() unless it's guaranteed // to have an .exe extension, eg. 'some.file' => 'some.file.dll', not 'some.dll' apphostExe.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) ? Path.ChangeExtension(apphostExe, ".dll") : apphostExe + ".dll"; int GetOffset(byte[] bytes, byte[] pattern) { int si = 0; var b = pattern[0]; while (si < bytes.Length) { si = Array.IndexOf(bytes, b, si); if (si < 0) break; if (Match(bytes, si, pattern)) return si; si++; } return -1; } bool Match(byte[] bytes, int index, byte[] pattern) { if (index + pattern.Length > bytes.Length) return false; for (int i = 0; i < pattern.Length; i++) { if (bytes[index + i] != pattern[i]) return false; } return true; }