Microsoft MVP성태의 닷넷 이야기
글쓴 사람
홈페이지
첨부 파일
 

.NET Framework 버전을 올렸을 때 오류가 발생할 수 있는 상황

아래와 같은 질문이 있는데,

CLR20r3 관련된 윈도우 오류입니다. ㅠㅠ 도와주세요.
; https://www.sysnet.pe.kr/3/0/5210

재현은 다음의 코드를 빌드해 .NET Framework 4.8이 설치된 환경에서 실행하면,

using System.Reflection;
using System.Windows;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var PresentationFramework = typeof(FrameworkElement).Assembly;
            var SystemResources = PresentationFramework.GetType("System.Windows.SystemResources");
            SystemResources.GetMethod("EnsureResourceChangeListener", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
        }
    }
}

AmbiguousMatchException 예외를 볼 수 있습니다.

Unhandled Exception: System.Reflection.AmbiguousMatchException: Ambiguous match found.
   at System.RuntimeType.GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv, Type[] types, ParameterModifier[] modifiers)
   at System.Type.GetMethod(String name, BindingFlags bindingAttr)
   at ConsoleApp1.Program.Main(String[] args) in F:\ConsoleApp1\ConsoleApp1\Program.cs:line 12

반면, .NET Framework 4.7 이하에서 실행하면 오류가 발생하지 않습니다.




원인은 간단합니다. .NET 4.7 이하의 경우 SystemResources 타입에 EnsureResourceChangeListener 메서드가 하나뿐이지만,

private static void EnsureResourceChangeListener()

.NET 4.8 이후로는 3개가 되기 때문에,

private static void EnsureResourceChangeListener();
private static void EnsureResourceChangeListener(DpiUtil.HwndDpiInfo hwndDpiInfo);
private static void EnsureResourceChangeListener(DpiAwarenessContextValue dpiContextValue);

단순한 GetMethod가 아닌, 재정의된(overloaded) 메서드를 구분할 수 있는 인자 목록까지 지정한 GetMethod를 사용하도록 코드를 바꿔야 합니다.

// 3개의 메서드 이름이 같으므로 AmbiguousMatchException 예외 발생
// SystemResources.GetMethod("EnsureResourceChangeListener", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static).Invoke(null, null);

// 3개의 메서드 중에 인자를 하나도 갖지 않는(new Type[] {}) 메서드를 선택하므로 정상 동작
SystemResources.GetMethod("EnsureResourceChangeListener", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static
    , null, new Type[] { }, null).Invoke(null, null);

하지만 위와 같이 소스 코드를 변경하지 못하는, 즉, 질문자의 경우처럼 "VERITAS" 제품을 사용하는 상황이라면 해당 머신에는 .NET Framework 4.8을 설치해서는 안 됩니다. (설치했다면 당연히 삭제해야만 문제 해결이 됩니다.) 실제로 제품의 Q&A에도 보면,

Backup Exec console crashes after installing .NET Framework 4.8.
; https://www.veritas.com/support/en_US/article.100045500

다음 버전에서 해결할 거라는 언급을 하고 있습니다.

The fix for this issue will be included in the next release (20.5) of Backup Exec. This article will be updated when 20.5 is available.

따라서 20.5 버전의 제품이 나오기 전까지는 임시로 .NET Framework 4.8을 설치해서는 안 됩니다.




그런데, 이게 누구의 책임일까요? ^^

가만 보면, 하위 호환성을 깨뜨린 .NET Framework 측의 오류로 보이지만 한 번 더 생각해 보면 "internal"로 정의된 타입과 심지어 그것의 "private" 메서드를 .NET Reflection으로 임의 접근한 것이기 때문에 애당초 해당 타입과 메서드는 하위 호환성과는 무관한 문제입니다. 따라서 이런 경우에는 사용자 측 문제가 맞습니다.

그렇기 때문에 VERITAS 측에서도 마이크로소프트에 버그로 등록하는 식의 조치를 취하지 않고 자사의 제품을 업데이트해 수정한 버전을 내놓겠다는 식으로 처리하는 것입니다.




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

[연관 글]





[최초 등록일: ]
[최종 수정일: 8/24/2019 ]

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

비밀번호

댓글 쓴 사람
 




[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
12222정성태6/3/202022VS.NET IDE: 146. error information: "CryptQueryObject" (-2147024893/0x80070003)
12221정성태6/3/202042Windows: 168. 비어 있지 않은 디렉터리로 symbolic link(junction) 연결하는 방법
12220정성태6/3/202043.NET Framework: 907. C# DLL로부터 TLB 및 C/C++ 헤더 파일(TLH)을 생성하는 방법
12219정성태6/1/2020118.NET Framework: 906. C# - lock (this), lock (typeof(...))를 사용하면 안 되는 이유파일 다운로드1
12218정성태5/31/202076.NET Framework: 905. C# - DirectX 게임 클라이언트 실행 중 키보드 입력을 감지하는 방법
12217정성태5/24/202034오류 유형: 615. Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
12216정성태5/15/2020125.NET Framework: 904. USB/IP PROJECT를 이용해 C#으로 USB Keyboard 가상 장치 만들기
12215정성태5/12/2020145개발 환경 구성: 490. C# - (Wireshark의) USBPcap을 이용한 USB 패킷 모니터링파일 다운로드1
12214정성태5/5/2020117개발 환경 구성: 489. 정식 인증서가 있는 경우 Device Driver 서명하는 방법 (2) - UEFI/SecureBoot
12213정성태5/3/2020211개발 환경 구성: 488. (코드로 가상 USB 장치를 만들 수 있는) USB/IP PROJECT 소개
12212정성태5/1/2020105개발 환경 구성: 487. UEFI / Secure Boot 상태인지 확인하는 방법
12211정성태4/27/2020212개발 환경 구성: 486. WSL에서 Makefile로 공개된 리눅스 환경의 C/C++ 소스 코드 빌드
12210정성태4/20/2020313.NET Framework: 903. .NET Framework의 Strong-named 어셈블리 바인딩 (1) - app.config을 이용한 바인딩 리디렉션 [1]파일 다운로드1
12209정성태4/13/2020172오류 유형: 614. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우 (2)
12208정성태4/12/2020210Linux: 29. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우
12207정성태4/2/2020197스크립트: 19. Windows PowerShell의 NonInteractive 모드
12206정성태4/2/2020276오류 유형: 613. 파일 잠금이 바로 안 풀린다면? - The process cannot access the file '...' because it is being used by another process.
12205정성태4/2/2020179스크립트: 18. Powershell에서는 cmd.exe의 명령어를 지원하진 않습니다.
12204정성태4/1/2020170스크립트: 17. Powershell 명령어에 ';' (semi-colon) 문자가 포함된 경우
12203정성태3/18/2020364오류 유형: 612. warning: 'C:\ProgramData/Git/config' has a dubious owner: '...'.
12202정성태3/18/2020396개발 환경 구성: 486. .NET Framework 프로젝트를 위한 GitLab CI/CD Runner 구성
12201정성태3/18/2020198오류 유형: 611. git-credential-manager.exe: Using credentials for username "Personal Access Token".
12200정성태3/18/2020491VS.NET IDE: 145. NuGet + Github 라이브러리 디버깅 관련 옵션 3가지 - "Enable Just My Code" / "Enable Source Link support" / "Suppress JIT optimization on module load (Managed only)"
12199정성태3/17/2020191오류 유형: 610. C# - CodeDomProvider 사용 시 Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '...\f2_6uod0.tmp'.
12198정성태3/17/2020202오류 유형: 609. SQL 서버 접속 시 "Cannot open user default database. Login failed."
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...