2009-10-02 2 views
57

.NET에서 '플랫폼 대상 : 모든 CPU'컴파일러 옵션을 사용하면 .NET 어셈블리가 x64 컴퓨터에서 64   비트로 실행될 수 있고 32   비트가 켜짐 x86 컴퓨터. 'Platform Target : x86'컴파일러 옵션을 사용하여 x64 컴퓨터에서 x86으로 어셈블리를 실행하도록 할 수도 있습니다.'모든 CPU'.NET 어셈블리에서 x86 CLR 강제 수행

'Any CPU'플래그를 사용하여 어셈블리를 실행할 수 있지만 x86 또는 x64 CLR에서 실행해야하는지 여부를 결정할 수 있습니까? 일반적으로이 결정은 기본 시스템의 bitness를 기반으로 CLR/OS 로더에 의해 결정됩니다 (필자의 이해대로).

다른 실행중인 프로세스와 상호 작용할 수있는 (읽기 : 코드 삽입) C# .NET 응용 프로그램을 작성하려고합니다. x64 프로세스는 다른 x64 프로세스에만 삽입 할 수 있고 x86 프로세스는 x86과 동일하게 삽입 할 수 있습니다. 이상적으로는 JIT 컴파일과 모든 CPU 옵션을 사용하여 하나의 응용 프로그램을 x64 또는 x86 프로세스 (x64 시스템)에 주입하는 데 사용할 수 있습니다.

아이디어는 응용 프로그램이 모든 CPU으로 컴파일된다는 것입니다. x64 컴퓨터에서는 x64로 실행됩니다. 대상 프로세스가 x86 인 경우 자체 프로세스를 다시 시작해야하므로 CLR에서 x86 프로세스로 실행해야합니다. 이것이 가능한가?

답변

9

나는 이것을 시도한 이래로 오랜 시간이 걸렸지 만 어셈블리를 호출하는 프로세스의 비트가 x86 또는 x64로 JITed 될지 여부를 결정한다고 생각합니다.

작은 콘솔 응용 프로그램을 작성하여 x86으로 빌드하고 x64로 빌드하면 다른 하나를 실행하면 프로세스에로드 된 다른 어셈블리가 32 또는 64 비트로 실행됩니다. 이것은 물론 64 비트 시스템에서 실행되고 있다고 가정합니다.

+3

예 저는 x86 런처 어셈블리에서이를 감싸서 강제로 사용할 수 있다는 것을 알고 있습니다.하지만 '모든 CPU'컴파일 된 어셈블리에 대해 동적으로 강제 할 수 있는지 궁금합니다. 어쨌든 고마워, 내가 다른 것을 찾을 수 없으면 아마 이것으로 되돌아 갈거야. upvote하지만 충분하지 않은 담당자. – jeffora

+1

프로세스는 64 비트 또는 32 비트입니다. 어셈블리가 32 비트 프로세스에서로드되고 모든 CPU로 빌드 된 경우 64 비트 프로세스에서 64 비트로 JITed 될 32 비트로 JITed됩니다. 어셈블리를 호스트하는 어셈블리를 어떻게 계획합니까? – jnoss

6

내가이 문제를 해결할 수 있는지 여부는 확실하지 않습니다. 그러나 이것은 나의 경험이다.

호스트 응용 프로그램에서 A.exe (x86으로 컴파일 됨)이 있고 호스트 응용 프로그램에서 클라이언트 응용 프로그램 B.exe (ANY CPU으로 컴파일 됨)이 있습니다. System.Diagnostic.Process 클래스를 사용하여 을 A.exe에서 실행합니다.

문제는 지금은 64 시스템에서 두 가지를 넣어 경우, 다음 A.exe는 86로 실행됩니다 B.exe 반면 가 64로 실행할 것이다.

그러나 A.exe 전화 (Any CPU로 컴파일 c.dll) 조립 c 및 B.exec.dll를 호출하는 경우, 다음 c.dll을 그것을 호출하는 응용 프로그램을 따를 것이다

. 즉, A.exe을 호출하면 64 비트 시스템에서 x86 dll처럼 동작하지만 B.exe을 호출하면 x64처럼 동작합니다.

61

CorFlags 응용 프로그램을 사용하여 응용 프로그램을 실행하고 정적으로 변경하는 방법을 찾을 수 있습니다. 응용 프로그램 사용을 어떻게 실행되는지 알아 보려면 :

corflags /32bit+ <PathToExe> 

이 32 비트 프로세스로 실행 EXE 파일을 만들 것입니다 :

corflags <PathToExe> 

사용, 응용 프로그램 실행 방법을 변경하려면. 어셈블리를 실행하는 방법에 대한 정보는 PE 헤더에 저장됩니다.스택 오버플로 질문 How to find if a native DLL file is compiled as x64 or x86?을 참조하십시오.

런타임에 코드를 주입하려면 C++/COM에 .NET 프로파일 러를 작성해야합니다. 자세한 내용은 .NET Internals: The Profiling APIProfiling (Unmanaged API Reference)을 참조하십시오.

JitCompilationStarted 콜백을 구현하고 거기에서 작업해야합니다. 이 방향으로 나아가고 있다면, 당신은 x86과 x64 모두로 주입 DLL 파일을 만들어야 할 것입니다. 다음과 같은 환경 변수가 설정됩니다 일단 네이티브 DLL 파일은 CLR에 의해로드됩니다

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

당신이 다음 64 비트 버전은 '참조'64 개 비트 프로세스 것이다 올바르게 설정되어있는 경우와 32 bit 버전은 32-bit 프로세스를 볼 것입니다.

+0

정보 주셔서 감사합니다 :) 나는 corflags 응용 프로그램을 알고 있었지만 비슷한 결과를 런타임에 프로그래밍 방식으로 얻을 수있는 방법이 있는지 궁금합니다. – jeffora

+1

프로세스가 실행되면 컨텍스트를 변경할 수 없습니다! –

+0

런타임에 컨텍스트를 변경한다고해서 WOW 에뮬레이션 레이어에서 32 비트 프로세스가 실행되고있는 것만으로 PE 헤더에 비트를 설정하는 것이 아닙니다. 프로세스가 런타임시 상태를 저장하고 컨텍스트 전환을 수행하고 실행을 계속하는 방법을 볼 수 없습니다. 이 링크를 참조하십시오 : http://blogs.msdn.com/oldnewthing/archive/2008/12/22/9244582.aspx –

6

2 가지 (실제로는 3 가지) 바이너리를 작성하여 비슷한 결과를 보았습니다. 나는 내가 주입하려고 시도한 프로세스가 32 또는 64 비트인지 여부를 감지했습니다. 이 프로세스는 32 비트 또는 64 비트 버전의 주입 바이너리를 시작합니다 (앞에서 언급 한 것처럼 다시 시작하는 것과 반대).

지저분하게 들리지만, 출력 바이너리 복사본을 만들고 CorFlags 유틸리티를 사용하여 복사본을 32 비트로 강제 실행하는 빌드 후 이벤트를 사용하여 빌드시이 작업을 쉽게 수행 할 수 있습니다. 이 방법으로 응용 프로그램에 CorFlags 유틸리티를 배포 할 필요가 없습니다. 어쨌든 어떤 이유로 든 올바르지 않을 수 있습니다.

이것은 처음 아이디어와 매우 흡사하며 두 줄짜리 빌드 이벤트를 제외하고는 더 많은 작업이 필요 없다고 생각합니다.

관련 문제