Microsoft MVP성태의 닷넷 이야기
.NET Framework: 302. supportedRuntime 옵션과 System.BadImageFormatException 예외 [링크 복사], [링크+제목 복사],
조회: 34750
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 14개 있습니다.)

supportedRuntime 옵션과 System.BadImageFormatException 예외

최근에 다음과 같은 오류를 만났습니다.

badformat_appconfig_1.png

Unhandled Exception: System.BadImageFormatException: Could not load file or assembly 'ConsoleApplication1.exe' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
File name: 'ConsoleApplication1.exe'


머리로는 BadImageFormatException이 x86/x64의 불일치에서 오는 문제라고만 생각하고 있어서 제법 애를 먹었는데요. 원인은, .NET 4.0 대상으로 빌드한 응용 프로그램에 다음과 같은 supportedRuntime 정책을 적용했기 때문이었습니다.

<?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v2.0.50727"/>
        <supportedRuntime version="v4.0.30319"/>
    </startup>
</configuration>

즉, 4.0으로 빌드한 경우 v2.0.50727 항목으로 인해 오류가 발생한 것입니다. 이를 해결하려면, 다음과 같이 순서를 바꾸는 것도 가능은 합니다.

<?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0.30319"/>
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

그렇지만, 이런 식의 해결방법은 (동작은 하지만) 잘못 판단된 것입니다. 왜냐하면, 위의 프로그램을 .NET 2.0만 설치된 환경에서 실행하면 예외가 발생하기 때문입니다. 즉, 2.0의 supportedRuntime을 두 번째 선택으로 미뤄놓은 아무런 의미가 없는 것입니다.

그렇다면, supportedRuntime이 언제 의미가 있는 것일까요?




supportedRuntime은 사실, 하위 버전으로 빌드된 어셈블리를 상위버전의 환경에서 구동할 때 호환을 위해 명시해 주는 데 의미가 있습니다. 간단하게 예를 들어볼까요?

다음과 같은 Console 응용 프로그램을 만들고,

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Environment.Version.ToString());
    }
}

이를 .NET 2.0으로 컴파일 합니다. 이 상태에서, 아래와 같은 app.config 구성으로 .NET 2.0/4.0이 모두 설치된 컴퓨터에서 실행하면 어떤 결과가 나올까요?

<?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0.30319"/> 
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

"v4.0.30319"가 위에 있으니 Environment.Version 출력값은 (제 컴퓨터 기준으로) "4.0.30319.239"입니다. 반면, 버전 번호의 자리를 바꿔서 출력하면 이번엔 "v2.0.50727"이 위에 있으므로 (제 컴퓨터 기준으로) "2.0.50727.5448" 결괏값이 나옵니다.

정리해 보면, supportedRuntime은 하위 버전의 응용 프로그램이 어떤 .NET Framework 런타임에서 실행할지를 결정하는 옵션입니다. 따라서, 처음 이 글의 문제로 돌아가서, supportedRuntime의 순서를 바꿀 것이 아니라 해당 응용 프로그램을 .NET 2.0 대상으로 빌드하는 것이 적절한 해결책입니다. (아니면, 아예 모든 supportedRuntime 옵션을 제거하든가.)

참고로, 기타 supportedRuntime의 종류에 관해서는 예전에 정리둔 것이 있으니 한번 봐두시는 것도 좋겠습니다. ^^

app.config의 supportedRuntime 종류
; https://www.sysnet.pe.kr/2/2/178




간단한 문제를 내 볼까요? ^^ 그렇다면 .NET 2.0으로 빌드된 exe를 아무런 app.config 파일 없이 .NET 4.0만 설치된 컴퓨터에서 실행하면 어떻게 될까?

그런 경우, 다음과 같이 예외가 발생합니다.

badformat_appconfig_2.png

.NET Framework Initialization Error
Unable to find a version of the runtime to run this application.

만약, 이 응용 프로그램을 정상적으로 구동하고 싶다면 app.config에 다음과 같은 설정을 추가해 주면 됩니다.

<?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0.30313"/>
    </startup>
</configuration>

또 다른 경우를 생각해 볼까요? .NET 1.1 exe 파일을 .NET 1.1/4.0은 설치되었지만 .NET 2.0이 설치되지 않은 컴퓨터에서 다음과 같이 2.0을 지원한다고 지정해 두면 어떻게 될까요?

<?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

이런 경우에도 역시 예외가 발생하면서 실행은 안되지만, 다행히 2.0을 설치할 것인지를 물어보는 대화상자가 뜹니다.

badformat_appconfig_3.png

To run this application, you first must install one of the following versions of the .NET Framework: v2.0.50727

Would you like to download and install version v2.0.50727 of the .NET Framework now?

이번엔 닷넷 프레임워크 버전 격차를 늘려서, .NET 1.1 exe 파일을 .NET 4.0만 설치된 컴퓨터에서 다음과 같이 4.0을 지원한다고 지정해 두면 어떻게 될까요?

<?xml version="1.0"?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0.30319"/>
    </startup>
</configuration>

걱정하지 마세요. ^^ (대부분의 경우) 실행이 아주 잘됩니다. 여기서 supportedRuntime을 가장 극적으로 사용할 수 있는 사례가 나옵니다. 즉, .NET 1.x/2.0/3.0/3.5/4.0에 상관없이 실행되어야 할 프로그램을 만들어야 한다면 해당 응용 프로그램은 .NET 1.1 버전으로 빌드하고 다음과 같이 supportedRuntime 목록을 구성해 주면 되는 것입니다.

<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v1.1.4322"/>
    <supportedRuntime version="v2.0.50727"/>
    <supportedRuntime version="v4.0.30319"/>
  </startup>
</configuration>

또는 일반적으로 최신 버전의 닷넷 프레임워크가 성능이 더 나아지기 때문에 다중 CLR이 설치된 경우에는 가장 최신의 것을 적용받도록 다음과 같이 거꾸로 순서를 지정하는 것도 좋습니다.

<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0.30319"/>
    <supportedRuntime version="v2.0.50727"/>
    <supportedRuntime version="v1.1.4322"/>
  </startup>
</configuration>

어떤 설정이든, .NET 1.1로 빌드된 응용 프로그램은 어떤 버전의 닷넷 프레임워크라도 설치되어 있으면 정상적으로 실행이 될 것입니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/26/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2014-04-29 02시29분
[spowner] 항상 간지러운 곳을 긁어 주셔서 감사합니다.
[guest]
2017-01-05 05시40분
[이지영] 프로그램 실행하는데 아래 같은 CLR20r3 오류가 나와 검색 끝에 여기까지 오게 되었는데요.

혹시 아래 오류 해결 조언 좀 부탁드려도 될까요? 위에 있는 방법으로 Transistor.exe.config라는 파일을 txt로 수정해서 해봤는데 설치 메세지만 뜨고..

어떻게 해야 할지를 모르겠습니다. 넷프레임은 1.1하고 4.6.2가 설치 되어 있습니다.. 이쪽 분야에 전문가분이신 것 같은데 조언 좀 부탁드려요.


문제 서명:
  문제 이벤트 이름: CLR20r3
  문제 서명 01: Transistor.exe
  문제 서명 02: 1.0.0.0
  문제 서명 03: 53b44d4e
  문제 서명 04: MonoGame.Framework.Windows
  문제 서명 05: 2.0.0.0
  문제 서명 06: 539b9ca8
  문제 서명 07: d7d
  문제 서명 08: cf
  문제 서명 09: U5BUGYMB24YGE00VAJPF2KCRJNMKDEEE
  OS 버전: 6.1.7601.2.1.0.256.1
  로캘 ID: 1042
  추가 정보 1: 8eed
  추가 정보 2: 8eed98f8b73ca44fd30d1b635a59cc65
  추가 정보 3: ff9f
  추가 정보 4: ff9f26c412fe1114ca0cbb0f7bc711a5
[guest]
2017-01-06 12시35분
CLR20r3 문제는 해당 프로그램을 만든 개발자도 해결하기 힘든 문제에 속합니다. 외부 개발자의 경우 어찌어찌 문제의 원인은 파악할 수 있어도 그렇다고 해결할 수 있는 것은 아닙니다. 경우에 따라 소스 코드를 변경해야 하기 때문인데요. 따라서 이런 문제는 Transistor.exe를 개발한 측에 물어보는 것이 가장 좋습니다.
정성태
2017-01-06 05시01분
[이지영] 아주 해결하기 어려운 문제인가 보군요. 조언 정말 감사합니다.
[guest]
2017-01-09 05시38분
[정환나라] // 이지영 //
.Net Framework를 4.0이나 2.0을 추가로 설치해 보세요.
[guest]

... 106  107  108  109  110  111  112  113  114  115  116  117  118  119  [120]  ...
NoWriterDateCnt.TitleFile(s)
10957정성태5/3/201628097오류 유형: 328. 윈도우 백업 시 오류 - 0x80780166 두 번째 이야기 [1]
10956정성태5/3/201624134Windows: 117. BitLocker - This device can't use a Trusted Platform Module.
10955정성태5/3/201630944.NET Framework: 581. C# - 순열(Permutation) 예제 코드파일 다운로드2
10954정성태5/3/201631690.NET Framework: 580. C# - 조합(Combination) 예제 코드 [2]파일 다운로드1
10953정성태5/2/201620435.NET Framework: 579. Assembly.LoadFrom으로 로드된 어셈블리의 JIT 컴파일 코드 공유?파일 다운로드1
10952정성태5/2/201623300.NET Framework: 578. 도메인 중립적인 어셈블리가 비-도메인 중립적인 어셈블리를 참조하는 경우파일 다운로드1
10951정성태5/2/201621107.NET Framework: 577. CLR Profiler로 살펴보는 SharedDomain의 모듈 로드 동작파일 다운로드1
10950정성태5/2/201628150.NET Framework: 576. 기본적인 CLR Profiler 소스 코드 설명 [2]파일 다운로드2
10949정성태4/28/201620662.NET Framework: 575. SharedDomain과 JIT 컴파일파일 다운로드1
10948정성태4/28/201625265.NET Framework: 574. .NET - 눈으로 확인하는 SharedDomain의 동작 방식 [3]파일 다운로드1
10947정성태4/27/201623099.NET Framework: 573. .NET CLR4 보안 모델 - 4. CLR4 보안 모델에서의 조건부 APTCA 역할파일 다운로드1
10946정성태4/26/201625983VS.NET IDE: 106. Visual Studio 2015 확장 - INI 파일을 위한 사용자 정의 포맷 기능 (Syntax Highlighting)파일 다운로드1
10945정성태4/26/201618967오류 유형: 327. VSIX 프로젝트 빌드 시 The "VsTemplatePaths" task could not be loaded from the assembly 오류 발생
10944정성태4/22/201620886디버깅 기술: 80. windbg - 풀 덤프 파일로부터 텍스트 파일의 내용을 찾는 방법
10943정성태4/22/201625810디버깅 기술: 79. windbg - 풀 덤프 파일로부터 .NET DLL을 추출/저장하는 방법 [1]
10942정성태4/19/201621172디버깅 기술: 78. windbg 사례 - .NET 예외가 발생한 시점의 오류 분석 [1]
10941정성태4/19/201620702오류 유형: 326. Error MSB8020 - The build tools for v120_xp (Platform Toolset = 'v120_xp') cannot be found.
10940정성태4/18/201624523Windows: 116. 프로세스 풀 덤프 시간을 줄여 주는 Process Reflection [3]
10939정성태4/18/201625366.NET Framework: 572. .NET APM 비동기 호출의 Begin...과 End... 조합 [3]파일 다운로드1
10938정성태4/13/201624125오류 유형: 325. 파일 삭제 시 오류 - Error 0x80070091: The directory is not empty.
10937정성태4/13/201632780Windows: 115. UEFI 모드로 윈도우 10 설치 가능한 USB 디스크 만드는 방법
10936정성태4/8/201644022Windows: 114. 삼성 센스 크로노스 7 노트북의 운영체제를 USB 디스크로 새로 설치하는 방법 [3]
10935정성태4/7/201628391웹: 32. Edge에서 Google Docs 문서 편집 시 한영 전환키가 동작 안하는 문제
10934정성태4/5/201626299디버깅 기술: 77. windbg의 콜스택 함수 인자를 쉽게 확인하는 방법 [1]
10933정성태4/5/201631752.NET Framework: 571. C# - 스레드 선호도(Thread Affinity) 지정하는 방법 [8]파일 다운로드1
10932정성태4/4/201624375VC++: 96. C/C++ 식 평가 - printf("%d %d %d\n", a, a++, a);
... 106  107  108  109  110  111  112  113  114  115  116  117  118  119  [120]  ...