You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

关于.NET Core受信任程序集DLL注入及.NET 6.0加载自定义System.Diagnostics.Process.dll的技术问询

.NET Core受信任程序集DLL注入及.NET 6.0加载自定义System.Diagnostics.Process.dll的技术问询

嘿,这个需求我太熟了——之前帮好几个开发者解决过类似的.NET框架核心程序集替换问题,直接给你说结论:完全可以实现,但得绕开.NET 6默认的程序集加载安全限制,还要分场景操作

先给你理清楚核心逻辑:.NET 6的程序集加载器会优先从「受信任平台程序集(TPA)列表」加载框架核心DLL(比如System.Diagnostics.Process.dll),这些DLL要么来自全局共享框架,要么来自独立发布应用自带的框架目录。要让它加载你放在工作目录的自定义DLL,得明确告诉加载器「别用默认的,用我这个本地的」。

下面是具体的可行方案,按操作难度从易到难排序:

方案一:修改.deps.json强制定向到自定义DLL

这是最直接的方法,适合**框架依赖(Framework-Dependent)**的应用:

  • 找到你应用根目录下的[你的应用名].deps.json文件,用文本编辑器打开
  • 搜索"System.Diagnostics.Process"的条目,它默认大概长这样:
    "System.Diagnostics.Process": {
      "version": "6.0.0",
      "serviceable": true,
      "sha512": "这里是原框架DLL的哈希值"
    }
    
  • 把它改成这样:
    "System.Diagnostics.Process": {
      "version": "6.0.0",
      "path": "System.Diagnostics.Process.dll",
      "sha512": "这里换成你自定义DLL的SHA512哈希值"
    }
    

    注意:哈希值必须完全匹配!你可以用dotnet hash System.Diagnostics.Process.dll命令生成正确的哈希字符串,复制进去就行

  • 把你的自定义System.Diagnostics.Process.dll放到应用的工作目录,和.exe同级别
  • 启动应用,加载器就会优先读取你指定的本地DLL了

如果是**独立发布(Self-Contained)**的应用,操作更简单:

  • 找到发布目录里的runtimes/[你的系统RID]/lib/net6.0文件夹(比如Windows x64就是runtimes/win-x64/lib/net6.0
  • 把里面原生的System.Diagnostics.Process.dll替换成你的自定义版本,同样要保证版本号、哈希完全匹配
  • 直接启动应用即可

方案二:用启动钩子(Startup Hook)拦截加载

如果修改.deps.json对你来说不太方便(比如应用会自动生成这个文件),可以用.NET的启动钩子机制来动态拦截程序集加载:

  • 写一个简单的类库项目,代码如下:
    using System;
    using System.IO;
    using System.Runtime.Loader;
    
    namespace ProcessHook
    {
        public class StartupHook
        {
            public static void Initialize()
            {
                // 拿到自定义DLL的路径
                var customDllPath = Path.Combine(Directory.GetCurrentDirectory(), "System.Diagnostics.Process.dll");
                // 给默认的程序集加载上下文添加解析钩子
                AssemblyLoadContext.Default.Resolving += (ctx, assemblyName) =>
                {
                    if (assemblyName.Name.Equals("System.Diagnostics.Process", StringComparison.OrdinalIgnoreCase))
                    {
                        return ctx.LoadFromAssemblyPath(customDllPath);
                    }
                    return null;
                };
            }
        }
    }
    
  • 把这个类库编译成.NET 6的DLL,放到应用工作目录
  • 启动应用前,设置环境变量:set DOTNET_STARTUP_HOOKS=ProcessHook.dll(Windows)或者export DOTNET_STARTUP_HOOKS=ProcessHook.dll(Linux/macOS)
  • 启动应用,钩子会在应用初始化前拦截Process.dll的加载,转而加载你的自定义版本

要踩的坑和注意事项

  • 版本和哈希必须严格匹配:.NET 6的加载器会校验程序集的版本号、哈希值,不匹配直接拒绝加载,别偷懒跳过这一步
  • 共享框架的优先级问题:如果是框架依赖的应用,你必须在.deps.json里明确指定本地路径,否则加载器还是会从全局共享框架拿DLL
  • 安全限制:如果你的应用跑在有安全策略的环境里(比如企业域、云托管平台),自定义框架DLL可能会被安全软件拦截,或者被.NET的安全机制阻止
  • 兼容性风险:替换核心框架DLL可能会导致其他依赖System.Diagnostics.Process的代码出问题,比如某些第三方库依赖原生行为,建议先在测试环境充分验证

额外的替代思路

其实你要实现的是「把alpha.exe替换成beta.exe」,不一定非要替换Process.dll——如果能修改原应用的代码,直接在调用Process.Start()前替换FileName就行;如果不能改原代码,也可以用IL织入或者反射拦截的方式,在运行时修改ProcessStartInfo.FileName的赋值,这样比替换框架DLL更安全,也不容易出兼容性问题。

比如用反射直接修改私有字段的示例(如果能在自己的辅助DLL里执行的话):

var processStartInfo = new ProcessStartInfo("alpha.exe");
// 用反射拿到私有字段_fileName
var fileNameField = typeof(ProcessStartInfo).GetField("_fileName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
fileNameField.SetValue(processStartInfo, "beta.exe");
new Process { StartInfo = processStartInfo }.Start();

不过如果完全碰不到原应用的代码,那还是回到前面的替换DLL方案最直接。有问题随时问,我再给你补细节!

火山引擎 最新活动