Microsoft MVP성태의 닷넷 이야기
.NET Framework: 302. supportedRuntime 옵션과 System.BadImageFormatException 예외 [링크 복사], [링크+제목 복사],
조회: 33283
글쓴 사람
정성태 (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)
11274정성태8/22/201719373.NET Framework: 674. Thread 타입의 Suspend/Resume/Join 사용 관련 예외 처리
11273정성태8/22/201721633오류 유형: 415. 윈도우 업데이트 에러 Error 0x80070643
11272정성태8/21/201724792VS.NET IDE: 120. 비주얼 스튜디오 2017 버전 15.3.1 - C# 7.1 공개 [2]
11271정성태8/19/201719230VS.NET IDE: 119. Visual Studio 2017에서 .NET Core 2.0 프로젝트 환경 구성하는 방법
11270정성태8/17/201730714.NET Framework: 673. C#에서 enum을 boxing 없이 int로 변환하기 [2]
11269정성태8/17/201721486디버깅 기술: 93. windbg - 풀 덤프에서 .NET 스레드의 상태를 알아내는 방법
11268정성태8/14/201721057디버깅 기술: 92. windbg - C# Monitor Lock을 획득하고 있는 스레드 찾는 방법
11267정성태8/10/201725115.NET Framework: 672. 모노 개발 환경
11266정성태8/10/201724917.NET Framework: 671. C# 6.0 이상의 소스 코드를 Visual Studio 설치 없이 명령행에서 컴파일하는 방법
11265정성태8/10/201753170기타: 66. 도서: 시작하세요! C# 7.1 프로그래밍: 기본 문법부터 실전 예제까지 [11]
11264정성태8/9/201724083오류 유형: 414. UWP app을 signtool.exe로 서명 시 0x8007000b 오류 발생
11263정성태8/9/201719569오류 유형: 413. The C# project "..." is targeting ".NETFramework, Version=v4.0", which is not installed on this machine. [3]
11262정성태8/5/201718248오류 유형: 412. windbg - SOS does not support the current target architecture. [3]
11261정성태8/4/201720833디버깅 기술: 91. windbg - 풀 덤프 파일로부터 강력한 이름의 어셈블리 추출 후 사용하는 방법
11260정성태8/3/201718935.NET Framework: 670. C# - 실행 파일로부터 공개키를 추출하는 방법
11259정성태8/2/201718172.NET Framework: 669. 지연 서명된 어셈블리를 sn.exe -Vr 등록 없이 사용하는 방법
11258정성태8/1/201718978.NET Framework: 668. 지연 서명된 DLL과 서명된 DLL의 차이점파일 다운로드1
11257정성태7/31/201719162.NET Framework: 667. bypassTrustedAppStrongNames 옵션 설명파일 다운로드1
11256정성태7/25/201720656디버깅 기술: 90. windbg의 lm 명령으로 보이지 않는 .NET 4.0 ClassLibrary를 명시적으로 로드하는 방법 [1]
11255정성태7/18/201723208디버깅 기술: 89. Win32 Debug CRT Heap Internals의 0xBAADF00D 표시 재현 [1]파일 다운로드3
11254정성태7/17/201719569개발 환경 구성: 322. "Visual Studio Emulator for Android" 에뮬레이터를 "Android Studio"와 함께 쓰는 방법
11253정성태7/17/201719913Math: 21. "Coding the Matrix" 문제 2.5.1 풀이 [1]파일 다운로드1
11252정성태7/13/201718450오류 유형: 411. RTVS 또는 PTVS 실행 시 Could not load type 'Microsoft.VisualStudio.InteractiveWindow.Shell.IVsInteractiveWindowFactory2'
11251정성태7/13/201717136디버깅 기술: 88. windbg 분석 - webengine4.dll의 MgdExplicitFlush에서 발생한 System.AccessViolationException의 crash 문제 (2)
11250정성태7/13/201720697디버깅 기술: 87. windbg 분석 - webengine4.dll의 MgdExplicitFlush에서 발생한 System.AccessViolationException의 crash 문제 [1]
11249정성태7/12/201718522오류 유형: 410. LoadLibrary("[...].dll") failed - The specified procedure could not be found.
... [106]  107  108  109  110  111  112  113  114  115  116  117  118  119  120  ...