2009-10-02 5 views
57

Dans .NET, l'option de compilateur 'Platform Target: Any CPU' permet à un assembly .NET de s'exécuter en tant que bit 64   sur un ordinateur x64 et 32 ​​bits   sur une machine x86. Il est également possible de forcer un assembly à s'exécuter en tant que x86 sur un ordinateur x64 à l'aide de l'option du compilateur 'Platform Target: x86'.Force x86 CLR sur un assembly 'Any CPU' .NET

Est-il possible d'exécuter un assembly avec l'indicateur 'Any CPU', mais déterminez s'il doit être exécuté dans le CLR x86 ou x64? Normalement, cette décision est prise par le chargeur CLR/OS (comme je le comprends) en fonction de la quantité de bit du système sous-jacent. J'essaie d'écrire une application C# .NET qui peut interagir avec (lire: injecter du code dans) d'autres processus en cours d'exécution. Les processus x64 peuvent uniquement injecter dans d'autres processus x64, et la même chose avec x86. Idéalement, je voudrais tirer parti de la compilation JIT et de l'option CPU pour permettre à une seule application d'être utilisée pour injecter dans des processus x64 ou x86 (sur une machine x64).

L'idée est que l'application serait compilée comme Any CPU. Sur une machine x64, elle fonctionnerait sous x64. Si le processus cible est x86, il devrait se relancer, obligeant le CLR à l'exécuter en tant que x86. Est-ce possible?

Répondre

9

Cela fait un moment que j'ai essayé cela, mais je crois que la qualité du processus qui appelle l'assembly détermine s'il sera JITed comme x86 ou x64. Par conséquent, si vous écrivez une petite application console et que vous la construisez en tant que x86, et une autre en x64, l'exécution de l'une ou de l'autre entraînera l'exécution d'autres assemblys chargés en 32 ou 64 bits. Ceci, bien sûr, suppose que vous utilisez une machine 64 bits.

+3

Yeh Je suis conscient que vous pouvez le forcer en l'enveloppant dans un assemblage de lanceur x86, mais je me demandais si vous pouviez le forcer dynamiquement pour les assemblys compilés 'Any CPU'. Merci quand même, reviendra probablement à cela si je ne trouve rien d'autre. Wouldvote mais pas assez rep. – jeffora

+1

Les processus sont 64 bits ou 32 bits. Si l'assembly est chargé dans un processus 32 bits et qu'il est construit comme Any CPU, il sera JITé en 32 bits, en 64 bits, il sera JITé en 64. Comment envisagez-vous de créer l'assembly qui héberge vos assemblées? – jnoss

6

Je ne sais pas si je peux vous aider avec ceci. Mais ceci est mon expérience.

J'ai une application hôte, A.exe (compilée en tant que x86), et j'ai une application client, B.exe (compilée en tant que ANY CPU), à partir de l'application hôte. Et je lance B.exe de A.exe, en utilisant la classe System.Diagnostic.Process.

La question est maintenant si je mets les deux sur une machine x64, puis A.exe se déroulera comme x86, alors que le B.exe se déroulera comme x64.

Mais si A.exe Assemblée appelle c (c.dll, qui est compilé en tant Any CPU), et B.exe appelle également c.dll, puis c.dll suivra l'application qui l'appelle. En d'autres termes, dans la machine 64 bit quand A.exe l'appelle, il se comportera comme x86 dll, alors que quand B.exe l'appelle, il se comportera comme x64.

61

Vous pouvez trouver comment l'application s'exécute et la modifier statiquement en utilisant l'application CorFlags. Pour savoir comment l'application fonctionnera, utilisez:

corflags <PathToExe> 

Pour modifier la façon dont l'application fonctionnera, utilisez:

corflags /32bit+ <PathToExe> 

Cela rendra le fichier EXE exécuter comme un processus 32 bits. Les informations sur l'exécution de l'assembly sont stockées dans l'en-tête PE.Voir la question de dépassement de pile How to find if a native DLL file is compiled as x64 or x86?.

Si vous souhaitez injecter du code lors de l'exécution, vous devez écrire un profileur .NET dans C++/COM. Voir .NET Internals: The Profiling API et Profiling (Unmanaged API Reference) pour plus de détails.

Vous devrez implémenter le rappel JitCompilationStarted et y faire votre travail. Si vous êtes dans cette direction, vous devrez construire le fichier DLL d'injection à la fois en x86 et x64. Les fichiers DLL natifs seront chargés par le CLR une fois que les variables d'environnement suivantes seront définies:

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

Si vous avez réglé correctement alors la version 64 bits « voir » les 64 processus de bits et 32- La version binaire "verra" les processus 32 bits.

+0

Merci pour l'info :) J'étais au courant de l'application corflags, mais je me demandais s'il y avait un moyen d'obtenir un résultat similaire par programmation à l'exécution. – jeffora

+1

Une fois que le processus est en cours, il est impossible de changer son contexte! –

+0

La modification du contexte au moment de l'exécution ne signifie pas simplement la définition d'un bit à l'en-tête PE, le processus 32 bits s'exécute sous la couche d'émulation WOW. Je ne vois pas comment le processus peut sauvegarder son état à l'exécution, faire un changement de contexte et continuer à fonctionner. Voir ce lien: http://blogs.msdn.com/oldnewthing/archive/2008/12/22/9244582.aspx –

6

J'ai fait quelque chose de similaire en créant deux (vraiment trois) binaires. J'ai eu un détecter si le processus que j'essayais d'injecter était de 32 ou 64 bits. Ce processus lancera alors la version 32 bits ou 64 bits de votre binaire d'injection (par opposition à la relance comme vous l'avez mentionné). Cela peut sembler compliqué, mais vous pouvez facilement y parvenir au moment de la construction avec un événement post-construction qui copie votre fichier binaire en sortie et utilise l'utilitaire CorFlags pour forcer la copie à s'exécuter en 32 bits. De cette façon, vous n'avez pas besoin de déployer l'utilitaire CorFlags avec votre application, ce qui n'est probablement pas légal pour une raison quelconque.

Je pense que cela est assez similaire à votre idée initiale et ne nécessite vraiment pas plus de travail, sauf pour un événement de construction de deux lignes.

Questions connexes