2009-10-02 11 views
57

En .NET, la opción del compilador 'Platform Target: Any CPU' permite que un ensamblado .NET se ejecute como 64   bit en una máquina x64, y 32   bit en una máquina x86. También es posible obligar a un ensamblaje a ejecutarse como x86 en una máquina x64 utilizando la opción del compilador 'Plataforma objetivo: x86'.Force x86 CLR en un ensamblado .NET 'Any CPU'

¿Es posible ejecutar un ensamblaje con el indicador 'Cualquier CPU', pero determine si debe ejecutarse en el CLR x86 o x64? Normalmente, esta decisión la toma CLR/OS Loader (según entiendo) basada en la bitidez del sistema subyacente.

Estoy tratando de escribir una aplicación C# .NET que pueda interactuar con (leer: introducir código en) otros procesos en ejecución. Los procesos x64 solo pueden inyectarse en otros procesos x64, y lo mismo con x86. Idealmente, me gustaría aprovechar la compilación JIT y la opción Any CPU para permitir que una sola aplicación se use para inyectar en procesos x64 o x86 (en una máquina x64).

La idea es que la aplicación se compilaría como Cualquier CPU. En una máquina x64, se ejecutaría como x64. Si el proceso objetivo es x86, debe reiniciarse, lo que obliga al CLR a ejecutarlo como x86. es posible?

Respuesta

9

Ha pasado un tiempo desde que probé esto, pero creo que la fragilidad del proceso que llama al ensamblado determina si se JITeará como x86 o x64.

Así que si escribe una aplicación de consola pequeña y la construye como x86, y otra como x64, ejecutar una u otra hará que otros ensamblajes cargados en el proceso se ejecuten como 32 o 64 bits. Esto, por supuesto, asume que se está ejecutando en una máquina de 64 bits.

+3

Yeh Soy consciente de que puede forzarlo envolviéndolo en un ensamblaje de iniciador x86, pero me preguntaba si podría forzarlo dinámicamente para ensamblajes compilados de 'Cualquier CPU'. Gracias de todos modos, probablemente volveré a esto si no puedo encontrar nada más. Sería votado pero no lo suficiente. – jeffora

+1

Los procesos son de 64 o 32 bits. Si el ensamblaje se carga en un proceso de 32 bits y está construido como Cualquier CPU, se JITeará como 32 bits, en el proceso de 64 bits se JITeará como 64. ¿Cómo piensa crear el ensamblaje que aloja sus ensamblajes? – jnoss

6

No estoy seguro de si puedo ayudarte con esto. Pero esta es mi experiencia.

tengo una aplicación host, A.exe (compilado como x86), y tengo una aplicación cliente, B.exe (compilado como ANY CPU), a partir de la aplicación host. Y lanzo B.exe de A.exe, usando la clase System.Diagnostic.Process.

La cuestión ahora es si pongo los dos en una máquina x64, entonces A.exe se ejecutará como x86, mientras que el B.exe se ejecutará como x64.

Pero si A.exe llamadas de montaje C (c.dll, que se compila como Any CPU), y B.exe también llamadas c.dll, entonces c.dll seguirá la aplicación que llama. En otras palabras, en una máquina de 64 bits cuando lo llame A.exe, se comportará como x86 dll, mientras que cuando B.exe lo llame, se comportará como x64.

61

Puede encontrar cómo se ejecutará la aplicación y cambiarla estáticamente utilizando la aplicación CorFlags. Para averiguar cómo se ejecutará la aplicación, uso:

corflags <PathToExe> 

Para cambiar la forma en la aplicación se ejecutará, utilice:

corflags /32bit+ <PathToExe> 

Esto hará que el archivo EXE se ejecute como un proceso de 32 bits. La información sobre cómo debe ejecutarse el ensamblaje se almacena en el encabezado PE.Consulte Pregunta de desbordamiento de pila How to find if a native DLL file is compiled as x64 or x86?.

Si desea inyectar código en tiempo de ejecución, debe escribir un generador de perfiles .NET en C++/COM. Ver .NET Internals: The Profiling API y Profiling (Unmanaged API Reference) para obtener más información.

Tendrá que implementar la devolución de llamada JitCompilationStarted y hacer su trabajo allí. Si estás en esta dirección, tendrás que compilar el archivo DLL de inyección tanto como x86 como x64. Los archivos DLL nativos serán cargados por el CLR una vez que se establecerán las siguientes variables de entorno:

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

Si lo ha configurado correctamente, entonces la versión de 64 bits será 'ver' los procesos de 64 bits y el 32- la versión de bit 'verá' los procesos de 32 bits.

+0

Gracias por la información :) Conocía la aplicación corflags, pero me preguntaba si había alguna forma de lograr un resultado similar programáticamente en tiempo de ejecución. – jeffora

+1

Una vez que el proceso se está ejecutando, ¡no hay manera de cambiar su contexto! –

+0

Cambiar el contexto en tiempo de ejecución no significa simplemente establecer un bit en el encabezado PE, el proceso de 32 bits se está ejecutando en la capa de emulación WOW. No puedo ver cómo el proceso puede guardar su estado en tiempo de ejecución, hacer un cambio de contexto y continuar ejecutando. Ver este enlace: http://blogs.msdn.com/oldnewthing/archive/2008/12/22/9244582.aspx –

6

He hecho algo similar creando dos (realmente tres) binarios. Tuve uno para detectar si el proceso que estaba tratando de inyectar era de 32 o 64 bits. Este proceso lanzará la versión de 32 bits o de 64 bits de su inyección binaria (en lugar de reiniciarse como usted mencionó).

Parece desordenado, pero puede lograrlo fácilmente en el momento de la compilación con un evento posterior a la compilación que hace una copia de su salida binaria y utiliza la utilidad CorFlags para forzar la copia a 32 bits. De esta forma, no tiene que implementar la utilidad CorFlags con su aplicación, que probablemente no sea legal por algún motivo de todos modos.

Creo que esto es bastante similar a su idea inicial y realmente no requiere más trabajo a excepción de un evento de compilación de dos líneas.

Cuestiones relacionadas