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

PublishFolderCleaner – Github

测试环境:

.Net 8

Program.cs 代码

// 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;
}

效果真不错

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/403802.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数学建模竞赛考点】近五年数维杯数学建模题型及算法模型总结

20204年第九届数维杯数学建模竞赛在5月10号开赛&#xff0c;为了帮助小伙伴们赛前充分准备&#xff0c;并且快速掌握历年的赛题类型&#xff0c;在这里给大家整理出了近五年的数维杯数学建模竞赛题目及考点方向&#xff0c;便于小伙伴们更好的巩固学习。 2019年 A题&#xff…

当项目经理的一定要考PMP嘛?

PMP资格认证并不是强制性要求&#xff0c;但强烈建议考虑获取该资格&#xff01;首先让我们来了解一下PMP是什么&#xff0c;然后再谈谈为什么建议考取PMP资格的理由。 PMP&#xff08;Project Management Professional&#xff09;是项目管理专业人员的资格认证。该认证由全球…

落雪音乐换源失败播放不了音乐——保姆级解决方法

不想看原因可以直接跳转到下面的解决方法 一、换源失败的原因二、解决方法注意&#xff01;2.1电脑版解决方法2.2 手机版解决方法前提&#xff08;必看&#xff01;&#xff09;解决方法 一、换源失败的原因 落雪开发者原话&#xff1a;虽然我们之前做了一些努力&#xff08;如…

《剑指Offer》笔记题解思路技巧优化_Part_7

《剑指Offer》笔记&题解&思路&技巧&优化_Part_7 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题&#x1f7e2;1. LCR 179. 查找总价格为目标值的两个商品——和…

ocr识别tesseract.js本地复现

来源&#xff1a; https://github.com/naptha/tesseract.js chatgpt今天帮倒忙&#xff0c;一直给一些旧的东西&#xff0c;代码就老报错&#xff0c;最后还是我出面看看log和err调了一下&#xff0c;还的是我啊 复现效果 这个挺好复现的&#xff0c;用的英文模式比中文识别…

Matlab/simulink光伏发电的扰动观察法MPPT仿真(持续更新)

1.光伏发电的电导增量法MPPT仿真 2.光伏发电的恒定电压法MPPT仿真 3.光伏发电的扰动观察法MPPT仿真 4.光伏发电的占空比法MPPT仿真 5.基于神经网络的MPPT光伏发电仿真 6. 基于模糊控制的MPPT光伏发电仿真 7. 基于粒子群算法&#xff08;PSO&#xff09;的500w光伏系统MPPT控…

如何使用Douglas-042为威胁搜索和事件应急响应提速

关于Douglas-042 Douglas-042是一款功能强大的PowerShell脚本&#xff0c;该脚本可以提升数据分类的速度&#xff0c;并辅助广大研究人员迅速从取证数据中筛选和提取出关键数据。 该工具能够搜索和识别Windows生态系统中潜在的安全漏洞&#xff0c;Douglas-042会将注意力放在…

小程序商城 免 费 搭 建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景+b2b2c

java SpringCloud版本b2b2c鸿鹄云商平台全套解决方案 使用技术&#xff1a; Spring CloudSpring BootMybatis微服务服务监控可视化运营 B2B2C平台&#xff1a; 平台管理端(包含自营) 商家平台端(多商户入驻) PC买家端、手机wap/公众号买家端 微服务&#xff08;30个通用…

ELF文件内容详解——各节内容分析

文章目录 写在前面准备.text节.data节.strtab.symtab.shstrtab.shstrtab之后 写在前面 只看readelf这个工具说实话我感觉还是有点云里雾里&#xff0c;这里就逐字节分析一下ELF文件中text节&#xff08;代码段&#xff09;的内容 本文分析使用的汇编程序ELF文件内容详解这篇文…

苍穹外卖Day02——总结2

前期文章 文章标题地址苍穹外卖Day01——总结1https://blog.csdn.net/qq_43751200/article/details/135466359?spm1001.2014.3001.5501苍穹外卖Day01——解决总结1中存在的问题https://lushimeng.blog.csdn.net/article/details/135473412 总结2 前期文章1. 新增员工模块1.1 …

ChatGPT调教指南 | 咒语指南 | Prompts提示词教程(一)

在我们开始探索人工智能的世界时&#xff0c;了解如何与之有效沉浸交流是至关重要的。想象一下&#xff0c;你手中有一把钥匙&#xff0c;可以解锁与OpenAI的GPT模型沟通的无限可能。这把钥匙就是——正确的提示词&#xff08;prompts&#xff09;。无论你是AI领域的新手&#…

【stm32】hal库学习笔记-UART/USART串口通信(超详细!)

【stm32】hal库学习笔记-UART/USART串口通信 hal库驱动函数 CubeMX图形化配置 导入LCD.ioc RTC设置 时钟树配置 设置LSE为RTC时钟源 USART设置 中断设置 程序编写 编写主函数 /* USER CODE BEGIN 2 */lcd_init();lcd_show_str(10, 10, 16, "Demo12_1:USART1-CH340&q…

CSS 字体和文本详解

CSS 字体和文本详解 字体设置 如果字体名有空格&#xff0c;使用引号包裹。建议使用常见字体&#xff0c; 否则兼容性不好。字体名称可以用英文&#xff0c;也可以用中文&#xff0c; 推荐使用英文。 示例代码: 运行结果: 字体大小 不同的浏览器默认字号不一样&#xff0c;…

学习Redis基础篇

1.初识Redis 1.认识NoSQL 2.认识Redis 3.连接redis命令 4.数据结构的介绍 5.通用命令 2.数据类型 1.String类型 常见命令&#xff1a;例子&#xff1a;set key value

vue-nextTick(nextTick---入门到离职系列)

官方定义 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的 DOM。 个人理解 假设我们更改了某个 dom 元素内部的文本&#xff0c;而这时候我们想直接打印这个更改之后的文本是需要 dom 更新之后才会实现的。 小案例 <tem…

NestJS入门2:创建模块

前文参考&#xff1a; NestJS入门1 1. 创建user模块 在项目目录下输入以下命令 nest g resource user 执行完后会在src文件夹下创建出user文件夹及文件夹下相应的文件&#xff0c;如下 2. 增加打印 3. 测试 &#xff08;1&#xff09;POSTBody Postman 服务端的打印 &…

关于在分布式环境中RVN和使用场景的介绍4

简介 在前面的文档中&#xff0c;我们介绍了RVN的概念&#xff0c;通过RVN可以解决的某类问题和使用技巧&#xff0c;以及处理RVN的逻辑的具体实现。在本文中&#xff0c;我们将要介绍关于如何使用RVN解决另一种在分布式系统中常出现的问题。 问题 假设我们创建了一个servic…

人工智能技术基础,AI技术基础知识,人工智能技术详解,无人机识别技术基础

什么是人工智能&#xff1f; 人工智能是计算机科学的一个分支&#xff0c;缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是研究使计算机来模拟人的某些思维过程和智能行为&#xff08;如学习、推理、思考、…

APP的UI自动化demo(appium+java)

文章目录 appium连接手机java代码实现-第一版第二版-接入testng和隐式等待显示等待 appium连接手机 准备工作 1、查看连接手机模拟器是否连接成功&#xff0c;获取设备名称 执行命令&#xff1a;adb devices 2、查看android内核版本号—>paltformVersion 执行命令&#xf…

企业微信变更企业主体的流程

企业微信变更主体有什么作用&#xff1f;做过企业运营的小伙伴都知道&#xff0c;很多时候经常会遇到现有的企业需要注销&#xff0c;切换成新的企业进行经营的情况&#xff0c;但是原来企业申请的企业微信上面却积累了很多客户&#xff0c;肯定不能直接丢弃&#xff0c;所以这…
最新文章