http://blog.naver.com/techshare/100151158445
위의 글을 퍼온겁니다.
머리로는 BadImageFormatException 이 x86/x64 의 불일치에서 오는 문제라고만 생각하고 있어서 제법 애를 먹었는데요. 원인은, .NET 4.0 대상으로 빌드한 응용 프로그램에 다음과 같은 supportedRuntime 정책을 적용했기 때문이었습니다.
즉, 4.0으로 빌드한 경우 v2.0.50727 항목으로 인해 오류가 발생한 것입니다. 이를 해결하려면, 다음과 같이 순서를 바꾸는 것도 가능은 합니다.
그렇지만, 이런 식의 해결방법은 (동작은 하지만) 잘못 판단된 것입니다. 왜냐하면, 위의 프로그램을 .NET 2.0 만 설치된 환경에서 실행하면 예외가 발생하기 때문입니다. 즉, 2.0의 supportedRuntime 을 두번째 선택으로 미뤄놓은 아무런 의미가 없는 것입니다.
그렇다면, supportedRuntime 이 언제 의미가 있는 것일까요?
supportedRuntime 은 사실, 하위 버전으로 빌드된 어셈블리를 상위버전의 환경에서 구동할 때 호환을 위해 명시해 주는 데 의미가 있습니다. 간단하게 예를 들어볼까요?
다음과 같은 Console 응용 프로그램을 만들고,
이를 .NET 2.0 으로 컴파일 합니다. 이 상태에서, 아래와 같은 app.config 구성으로 .NET 2.0/4.0 이 모두 설치된 컴퓨터에서 실행하면 어떤 결과가 나올까요?
"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 의 종류에 관해서는 예전에 정리둔 것이 있으니 한번 봐두시는 것도 좋겠습니다. ^^
간단한 문제를 내 볼까요? ^^ 그렇다면 .NET 2.0 으로 빌드된 exe 를 아무런 app.config 파일 없이 .NET 4.0 만 설치된 컴퓨터에서 실행하면 어떻게 될까?
그런 경우, 다음과 같이 예외가 발생합니다.
만약, 이 응용 프로그램을 정상적으로 구동하고 싶다면 app.config 에 다음과 같은 설정을 추가해 주면 됩니다.
또 다른 경우를 생각해 볼까요? .NET 1.1 exe 파일을 .NET 1.1/4.0은 설치되었지만 .NET 2.0 이 설치되지 않은 컴퓨터에서 다음과 같이 2.0 을 지원한다고 지정해 두면 어떻게 될까요?
이런 경우에도 역시 예외가 발생하면서 실행은 안되지만, 다행히 2.0 을 설치할 것인지를 물어보는 대화상자가 뜹니다.
이번엔 닷넷 프레임워크 버전 격차를 늘려서, .NET 1.1 exe 파일을 .NET 4.0 만 설치된 컴퓨터에서 다음과 같이 4.0 을 지원한다고 지정해 두면 어떻게 될까요?
걱정하지 마세요. ^^ (대부분의 경우) 실행이 아주 잘됩니다. 여기서 supportedRuntime 을 가장 극적으로 사용할 수 있는 사례가 나옵니다. 즉, .NET 1.x/2.0/3.0/3.5/4.0 에 상관없이 실행되어야 할 프로그램을 만들어야 한다면 해당 응용 프로그램은 .NET 1.1 버전으로 빌드하고 다음과 같이 supportedRuntime 목록을 구성해 주면 되는 것입니다.
또는 일반적으로 최신 버전의 닷넷 프레임워크가 성능이 더 나아지기 때문에 다중 CLR 이 설치된 경우에는 가장 최신의 것을 적용받도록 다음과 같이 거꾸로 순서를 지정하는 것도 좋습니다.
어떤 설정이든, .NET 1.1 로 빌드된 응용 프로그램은 어떤 버전의 닷넷 프레임워크라도 설치되어 있으면 정상적으로 실행이 될 것입니다.
위의 글을 퍼온겁니다.
최근에 다음과 같은 오류를 만났습니다.
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'
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.30313"/>
</startup>
</configuration>
즉, 4.0으로 빌드한 경우 v2.0.50727 항목으로 인해 오류가 발생한 것입니다. 이를 해결하려면, 다음과 같이 순서를 바꾸는 것도 가능은 합니다.
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0.30313"/>
<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 종류 ; http://www.sysnet.pe.kr/2/2/178
간단한 문제를 내 볼까요? ^^ 그렇다면 .NET 2.0 으로 빌드된 exe 를 아무런 app.config 파일 없이 .NET 4.0 만 설치된 컴퓨터에서 실행하면 어떻게 될까?
그런 경우, 다음과 같이 예외가 발생합니다.
.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 을 설치할 것인지를 물어보는 대화상자가 뜹니다.
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.30313"/> </startup> </configuration>
또는 일반적으로 최신 버전의 닷넷 프레임워크가 성능이 더 나아지기 때문에 다중 CLR 이 설치된 경우에는 가장 최신의 것을 적용받도록 다음과 같이 거꾸로 순서를 지정하는 것도 좋습니다.
<?xml version="1.0"?> <configuration> <startup> <supportedRuntime version="v4.0.30313"/> <supportedRuntime version="v2.0.50727"/> <supportedRuntime version="v1.1.4322"/> </startup> </configuration>
어떤 설정이든, .NET 1.1 로 빌드된 응용 프로그램은 어떤 버전의 닷넷 프레임워크라도 설치되어 있으면 정상적으로 실행이 될 것입니다.