在“任何CPU”.NET程序集上强制执行x86 CLR

在.NET中,“平台目标:任何CPU”编译器选项允许.NET程序集在x64机器上以64位运行,在x86机器上以32位运行。 也可以使用“Platform Target:x86”编译器选项强制程序集在x64机器上作为x86运行。

是否有可能使用“任何CPU”标志运行程序集,但确定它是否应该在x86或x64 CLR中运行? 正常情况下,这个决定是由CLR / OS Loader(根据我的理解)根据底层系统的位数来做出的。

我正在尝试编写一个C#.NET应用程序,它可以与其他正在运行的进程交互(读入:注入代码)。 x64进程只能注入到其他x64进程中,并且与x86一样。 理想情况下,我想利用JIT编译和Any CPU选项来允许单个应用程序用于注入x64或x86进程(在x64机器上)。

这个想法是,应用程序将被编译为任何CPU 。 在x64机器上,它将以x64运行。 如果目标进程是x86,则应该重新启动自己,强制CLR将其作为x86运行。 这可能吗?

您可以find应用程序如何运行,并使用CorFlags应用程序静态地进行更改。 要了解应用程序的运行方式,请使用:

corflags <PathToExe> 

要更改应用程序的运行方式,请使用:

 corflags /32bit+ <PathToExe> 

这将使EXE文件以32位进程运行。 有关如何运行程序集的信息存储在PE头中。 请参阅堆栈溢出问题如何查找本机DLL文件是否编译为x64或x86?

如果你想在运行时注入代码,你必须在C ++ / COM中编写一个.NET分析器。 有关更多详细信息,请参见.NET内部:概要分析API分析(非托pipeAPI参考)

你需要实现JitCompilationStartedcallback,并在那里做你的工作。 如果你在这个方向,你将不得不build立注入DLL文件都为x86和x64。 一旦下面的环境variables将被设置,本机DLL文件将由CLR加载:

 Cor_Enable_Profiling=0x1 COR_PROFILER={CLSID-of-your-native-DLL-file} 

如果你设置正确,那么64位版本将会“看到”64位进程,而32位版本将会看到32位进程。

自从我尝试这个以来已经有一段时间了,但是我相信调用程序集的进程的位数决定了它是否会被打成x86或x64。

因此,如果您编写一个小型控制台应用程序并将其构build为x86,另一个为x64,则运行其中一个或另一个将导致其他程序集加载到该进程中,以32位或64位运行。 这当然,假设你在一台64位的机器上运行。

我不确定我是否可以帮助你。 但这是我的经验。

我有一个主机应用程序, A.exe (编译为x86),并从主机应用程序有一个客户端应用程序, B.exe (编译为ANY CPU )。 我使用System.Diagnostic.Process类从A.exe启动B.exe

现在的问题是,如果我把这两个放在一台x64机器上,那么A.exe将作为x86运行, B.exe将作为x64运行

但是,如果A.exe调用程序集c( c.dll ,它被编译为Any CPU ),并且B.exe也调用c.dll ,那么c.dll将遵循调用它的应用程序。 换句话说,在A.exe调用它的64位机器时,它的行为将类似于x86 dll,而当B.exe调用它时,它的行为将类似于x64

我通过创build两个(真正的三个)二进制文件来做类似的事情。 我有一个检测是否我试图注入的过程是32位或64位。 然后这个过程会启动你的注入二进制文件的32位或者64位版本(而不是象你刚才提到的那样重新启动)。

这听起来很混乱,但是您可以在构build时使用生成输出二进制文件的副本并使用CorFlags实用程序强制副本以32位运行的方式轻松实现此目的。 通过这种方式,您不必在应用程序中部署CorFlags实用程序,无论如何这可能不合法。

我认为这与你最初的想法非常相似,除了两行build立事件外,实际上并不需要更多的工作。