C# 在“任何 CPU”.NET 程序集上强制 x86 CLR
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1507268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force x86 CLR on an 'Any CPU' .NET assembly
提问by jeffora
In .NET, the 'Platform Target: Any CPU' compiler option allows a .NET assembly to run as 64 bit on a x64 machine, and 32 bit on an x86 machine. It is also possible to force an assembly to run as x86 on an x64 machine using the 'Platform Target: x86' compiler option.
在 .NET 中,“平台目标:任何 CPU”编译器选项允许 .NET 程序集在 x64 机器上以 64 位运行,在 x86 机器上以 32 位运行。还可以使用“平台目标:x86”编译器选项强制程序集在 x64 机器上作为 x86 运行。
Is it possible to run an assembly with the 'Any CPU' flag, but determine whether it should be run in the x86 or x64 CLR? Normally this decision is made by the CLR/OS Loader (as is my understanding) based on the bitness of the underlying system.
是否可以运行带有“Any CPU”标志的程序集,但要确定它应该在 x86 还是 x64 CLR 中运行?通常这个决定是由 CLR/OS 加载器(根据我的理解)基于底层系统的位数做出的。
I am trying to write a C# .NET application that can interact with (read: inject code into) other running processes. x64 processes can only inject into other x64 processes, and the same with x86. Ideally, I would like to take advantage of JIT compilation and the Any CPUoption to allow a single application to be used to inject into either x64 or x86 processes (on an x64 machine).
我正在尝试编写一个 C# .NET 应用程序,它可以与(读取:将代码注入)其他正在运行的进程进行交互。x64进程只能注入其他x64进程,x86也一样。理想情况下,我想利用 JIT 编译和Any CPU选项来允许使用单个应用程序注入 x64 或 x86 进程(在 x64 机器上)。
The idea is that the application would be compiled as Any CPU. On an x64 machine, it would run as x64. If the target process is x86, it should relaunch itself, forcing the CLR to run it as x86. Is this possible?
这个想法是应用程序将被编译为Any CPU。在 x64 机器上,它将作为 x64 运行。如果目标进程是 x86,它应该重新启动自己,强制 CLR 作为 x86 运行它。这可能吗?
回答by jnoss
It has been a while since I tried this, but I believe that the bitness of the process that calls the assembly determines whether it will be JITed as x86 or x64.
自从我尝试这个已经有一段时间了,但我相信调用程序集的进程的位数决定了它是否会被 JIT 为 x86 或 x64。
So if you write a small console application and build it as x86, and another as x64, running one or the other will cause other assemblies loaded into the process to run as 32 or 64 bit. This, of course, assumes you are running on a 64 bit machine.
因此,如果您编写一个小型控制台应用程序并将其构建为 x86,另一个构建为 x64,运行其中一个将导致加载到进程中的其他程序集以 32 位或 64 位运行。当然,这假设您在 64 位机器上运行。
回答by Graviton
I'm not sure whether I can help you with this. But this is my experience.
我不确定我是否可以帮助你解决这个问题。但这是我的经验。
I have a host application,A.exe
( compiled as x86), and I have a client application, B.exe
( compiled as ANY CPU
), from the host application. And I launch B.exe
from A.exe
, using the System.Diagnostic.Processclass.
我有一个主机应用程序A.exe
(编译为 x86),我有一个来自主机应用程序的客户端应用程序B.exe
(编译为ANY CPU
)。我B.exe
从启动A.exe
,使用System.Diagnostic.Process类。
The issue now is if I put the two on a x64 machine, then A.exe
will run as x86, whereas the B.exe
will run as x64.
现在的问题是,如果我将两者放在 x64 机器上,A.exe
则将作为 x86 运行,而B.exe
将作为 x64 运行。
But if A.exe
calls assembly c ( c.dll
, which is compiled as Any CPU
), and B.exe
also calls c.dll
, then c.dll will follow the application that calls it. In other words, in 64 bit machine when A.exe
calls it, it will behave like x86
dll, whereas when B.exe
calls it, it will behave like x64
.
但是如果A.exe
调用程序集 c ( c.dll
,它被编译为Any CPU
),并且B.exe
还调用了c.dll
,那么 c.dll 将跟随调用它的应用程序。换句话说,在 64 位机器中A.exe
调用它时,它的行为类似于x86
dll,而B.exe
调用它时,它的行为类似于x64
.
回答by Ohad Horesh
You can find out how an application will run and change it statically using the CorFlagsapplication. To find out how the application will run, use:
您可以使用CorFlags应用程序了解应用程序将如何运行并对其进行静态更改。要了解应用程序将如何运行,请使用:
corflags <PathToExe>
To change how the application will run, use:
要更改应用程序的运行方式,请使用:
corflags /32bit+ <PathToExe>
This will make the EXE file run as a 32-bit process. The information about how the assembly should run is stored in the PE header. See Stack Overflow question How to find if a native DLL file is compiled as x64 or x86?.
这将使 EXE 文件作为 32 位进程运行。有关程序集应该如何运行的信息存储在 PE 标头中。请参阅堆栈溢出问题如何查找本机 DLL 文件是编译为 x64 还是 x86?.
If you want to inject code at run time, you have to write a .NETprofiler in C++/COM. See .NET Internals: The Profiling APIand Profiling (Unmanaged API Reference)for more details.
如果你想在运行时注入代码,你必须用C++/COM编写一个.NET分析器。有关更多详细信息,请参阅.NET Internals:Profiling API和Profiling(非托管 API 参考)。
You'll need to implement the JitCompilationStarted callback and do your work there. If you go in this direction, you'll have to build the injecting DLL file both as x86 and x64. The native DLL files will be loaded by the CLRonce the following environment variables will be set:
您需要实现 JitCompilationStarted 回调并在那里完成您的工作。如果朝这个方向发展,则必须将注入的 DLL 文件构建为 x86 和 x64。一旦设置了以下环境变量,CLR就会加载本机 DLL 文件:
Cor_Enable_Profiling=0x1
COR_PROFILER={CLSID-of-your-native-DLL-file}
If you have it set correctly then the 64-bit version will 'see' the 64 bit processes and the 32-bit version will 'see' the 32-bit processes.
如果设置正确,则 64 位版本将“看到”64 位进程,而 32 位版本将“看到”32 位进程。
回答by KarlW
I've done something similar by creating two (really three) binaries. I had one detect whether the process I was trying to inject into was 32 or 64-bit. This process will then launch either the 32-bit or 64-bit version of your injection binary (as opposed to relaunching itself like you mentioned).
我通过创建两个(实际上是三个)二进制文件做了类似的事情。我有一个检测我试图注入的进程是 32 位还是 64 位。然后,此过程将启动注入二进制文件的 32 位或 64 位版本(而不是像您提到的那样重新启动自己)。
It sounds messy, but you can easily achieve this at build time with a post-build event that makes a copy of your output binary and uses the CorFlagsutility to force the copy to run as 32-bit. This way you don't have to deploy the CorFlags utility with your application, which probably isn't legal for some reason anyway.
这听起来很混乱,但是您可以在构建时使用构建后事件轻松实现这一点,该事件生成输出二进制文件的副本并使用CorFlags实用程序强制副本以 32 位方式运行。这样您就不必在您的应用程序中部署 CorFlags 实用程序,这可能出于某种原因是不合法的。
I think this is quite similar to your initial idea and really doesn't require more work except for a two-line build event.
我认为这与您最初的想法非常相似,除了两行构建事件之外,实际上不需要更多工作。