是否可以在运行时覆盖 Environment.GetCommandLineArgs() ?
Is it possible to override Environment.GetCommandLineArgs() at runtime?
我正在开发一个“调试调度程序”C# 程序,它是一个调试辅助工具。这不是一个新的应用程序;它已成为该项目的一部分,并且在一段时间内对其进行调试非常宝贵。但是,它有一些限制,我一直在努力解决这些问题以实现更完整的调试体验。
此调试调度程序取代接受启动应用程序请求的系统服务,其目的是允许附加的调试器自动与通常在子进程中启动的代码进行交互。子进程本身就是 .NET 应用程序。
制作此工具时(几年前),首先调查的是是否有任何方法可以使用当前调试器启动子进程已经附加到它. None 被发现,因此该工具创建一个独立的 AppDomain
,在其中启动每个进程,然后将应用程序作为程序集加载并调用其入口方法。这 几乎 完美地工作,但我 运行 遇到的问题是,如果这些子进程调用 Environment.GetCommandLineArgs
,它们将获得调试调度程序工具的命令行而不是旨在传递给子进程的命令行。
我一直在努力寻找一种方法来覆盖Environment.GetCommandLineArgs
。
根据公开可用的源代码,看起来如果我的应用程序是 .NET Core,实际上会有一个内部方法 SetCommandLineArgs
我可以通过反射调用。这是内部的事实对我来说并不是特别麻烦,因为这个工具专门是一个 调试助手;如果它碰巧因为实施改变而中断了道路,那就这样吧。它在调试上下文之外没有任何作用,也永远不会出现在非开发机器上。但是....NET Core 和 .NET 5 根本不支持 AppDomains,而且永远不会,所以这是不可能的。
我尝试使用 Ryder 将 Environment.GetCommandLineArgs
重定向到我自己的实现,但它似乎不起作用,即使使用 .ini
文件指定 [.NET Framework Debugging Control]
节 AllowOptimize=0
。它几乎看起来好像 JIT 对这个特定方法有特殊处理,因为即使参考源显示它对本机方法进行 icall,当我请求在调试器中反汇编 JIT 输出时,它根本没有显示任何调用,直接从内联内存地址加载一个值。
我搜索了在 Win32 级别更改当前进程命令行的方法,但似乎无法修改。
在通过AppDomains(仅用于辅助调试)支持同一进程内多个并发应用程序的情况下,有没有办法拦截and/or覆盖Environment.GetCommandLineArgs
的 return 值,以便我可以支持通过该方法专门获取其命令行参数的托管应用程序?
好吧,我不确定我做了什么改变了它,但在某些时候使用 Ryder 重定向 Environment.GetCommandLineArgs
似乎变得不可靠(有些调用会重定向,有些不会 - - 在一些调试会话中,Ryder 似乎根本没有效果)到可靠(每个调用都被重定向)。 Ryder 的重定向显然不会自动应用于所有 AppDomain,因此我每次创建 AppDomain 时都必须重新安装它,之后我的经验是,如果我尝试卸载 AppDomain,进程就会死得一塌糊涂。但是,出于调试目的...我认为这已经足够了。
我正在开发一个“调试调度程序”C# 程序,它是一个调试辅助工具。这不是一个新的应用程序;它已成为该项目的一部分,并且在一段时间内对其进行调试非常宝贵。但是,它有一些限制,我一直在努力解决这些问题以实现更完整的调试体验。
此调试调度程序取代接受启动应用程序请求的系统服务,其目的是允许附加的调试器自动与通常在子进程中启动的代码进行交互。子进程本身就是 .NET 应用程序。
制作此工具时(几年前),首先调查的是是否有任何方法可以使用当前调试器启动子进程已经附加到它. None 被发现,因此该工具创建一个独立的 AppDomain
,在其中启动每个进程,然后将应用程序作为程序集加载并调用其入口方法。这 几乎 完美地工作,但我 运行 遇到的问题是,如果这些子进程调用 Environment.GetCommandLineArgs
,它们将获得调试调度程序工具的命令行而不是旨在传递给子进程的命令行。
我一直在努力寻找一种方法来覆盖Environment.GetCommandLineArgs
。
根据公开可用的源代码,看起来如果我的应用程序是 .NET Core,实际上会有一个内部方法
SetCommandLineArgs
我可以通过反射调用。这是内部的事实对我来说并不是特别麻烦,因为这个工具专门是一个 调试助手;如果它碰巧因为实施改变而中断了道路,那就这样吧。它在调试上下文之外没有任何作用,也永远不会出现在非开发机器上。但是....NET Core 和 .NET 5 根本不支持 AppDomains,而且永远不会,所以这是不可能的。我尝试使用 Ryder 将
Environment.GetCommandLineArgs
重定向到我自己的实现,但它似乎不起作用,即使使用.ini
文件指定[.NET Framework Debugging Control]
节AllowOptimize=0
。它几乎看起来好像 JIT 对这个特定方法有特殊处理,因为即使参考源显示它对本机方法进行 icall,当我请求在调试器中反汇编 JIT 输出时,它根本没有显示任何调用,直接从内联内存地址加载一个值。我搜索了在 Win32 级别更改当前进程命令行的方法,但似乎无法修改。
在通过AppDomains(仅用于辅助调试)支持同一进程内多个并发应用程序的情况下,有没有办法拦截and/or覆盖Environment.GetCommandLineArgs
的 return 值,以便我可以支持通过该方法专门获取其命令行参数的托管应用程序?
好吧,我不确定我做了什么改变了它,但在某些时候使用 Ryder 重定向 Environment.GetCommandLineArgs
似乎变得不可靠(有些调用会重定向,有些不会 - - 在一些调试会话中,Ryder 似乎根本没有效果)到可靠(每个调用都被重定向)。 Ryder 的重定向显然不会自动应用于所有 AppDomain,因此我每次创建 AppDomain 时都必须重新安装它,之后我的经验是,如果我尝试卸载 AppDomain,进程就会死得一塌糊涂。但是,出于调试目的...我认为这已经足够了。