Microsoft MVP성태의 닷넷 이야기
.NET Framework: 104. Win32Exception 클래스 소개 [링크 복사], [링크+제목 복사],
조회: 21013
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 


Win32Exception 클래스 소개


.NET으로 Win32 API를 interop으로 호출을 할 때, 실패를 하면 그 원인을 알아낼 수 없어서 답답하지요. .NET에서는 Exception 클래스에서 친절한 오류 메시지를 알아낼 수 있지만, Win32 API를 호출했을 때는 그렇지 않습니다.

예를 들어 아래와 같은 OpenProcessToken이라는 Win32 API를 이용할 때,

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(IntPtr processHandle, int acc, out IntPtr pHandleToken);

IntPtr tokenHandle = IntPtr.Zero;
IntPtr processHandle = new IntPtr(-2);

bool result
    = OpenProcessToken(processHandle,
    (int)(0x0020 | 0x00020000 | 0x0008),
    out tokenHandle);

위의 결과는 result == false가 나옵니다. 이런 경우, 왜 실패했는지를 알고 싶다면 Win32 API에서 제공되는 "GetLastError" API를 이용하면 되는데, 이 부분은 .NET BCL의 Marshal 타입에서 정적 메서드로 제공되고 있습니다. 그래서, 다음과 같이 그 원인을 알아낼 수 있습니다.

int errorCode = Marshal.GetLastWin32Error();

위와 같은 상황에서는 errorCode == 6입니다. 그런데, 6이라는 숫자가 어떤 걸 의미할까요? Visual C++에서는 Watch 윈도우의 변수에 ", hr"이라고 치면 오류값이 나옵니다. 아니면, 명령행 창에서 "NET HELPMSG <errorcode>"와 같이 치면 6에 대한 에러 메시지가 "The handle is invalid."라는 것을 알 수 있습니다. (Visual Studio 2008의 경우, C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\errlook.exe를 이용하는 것도 가능합니다.)

그렇다면, 코드로는 어떻게 알아낼 수 있을까요?

Visual C++에서는 FormatMessage Win32 API를 이용해서 오류 메시지를 얻어낼 수 있는데요. 인터넷 검색을 해보시면 아시겠지만, 코드가 그다지 깔끔하게 나오지는 않습니다. 기왕이면, .NET에서 제공되는 좀 더 매끄러운 방법을 찾아보는 것이 좋겠지요. ^^

제가 처음에 생각해 냈던 것은 아래와 같은 코드였습니다.

int hr = Marshal.GetHRForLastWin32Error();
Exception ex = Marshal.GetExceptionForHR(hr);
string errorMessage = ex.Message;

실제로 errorMessage == "The handle is invalid. (Exception from HRESULT: 0x80070006 (E_HANDLE))"라고 해서 만족할 만한 수준입니다. 나름 위의 방법도 답이 될 수도 있지만, 원래 Microsoft에서 제공되는 전용 타입이 있는 데 그것이 바로 "Win32Exception"입니다.

그래서, 최종적으로 다음과 같이 코딩을 할 수 있습니다.

int errorCode = Marshal.GetLastWin32Error();
Exception ex = new Win32Exception(errorCode);
string errorMessage = ex.Message; // "The handle is invalid."





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







[최초 등록일: ]
[최종 수정일: 7/10/2021]

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

비밀번호

댓글 작성자
 




... 46  47  [48]  49  50  51  52  53  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12737정성태7/28/202115012오류 유형: 744. Azure Active Directory - The resource principal named api://...[client_id]... was not found in the tenant
12736정성태7/28/202115275오류 유형: 743. Active Azure Directory에서 "API permissions"의 권한 설정이 "Not granted for ..."로 나오는 문제
12735정성태7/27/202115174.NET Framework: 1081. C# - Azure AD 인증을 지원하는 데스크톱 애플리케이션 예제(Windows Forms) [2]파일 다운로드1
12734정성태7/26/202131992스크립트: 20. 특정 단어로 시작하거나/끝나는 문자열을 포함/제외하는 정규 표현식 - Look-around
12733정성태7/23/202119876.NET Framework: 1081. Self-Contained/SingleFile 유형의 .NET Core/5+ 실행 파일을 임베딩한다면? [1]파일 다운로드2
12732정성태7/23/202113313오류 유형: 742. SharePoint - The super user account utilized by the cache is not configured.
12731정성태7/23/202115363개발 환경 구성: 584. Add Internal URLs 화면에서 "Save" 버튼이 비활성화 된 경우
12730정성태7/23/202116789개발 환경 구성: 583. Visual Studio Code - Go 코드에서 입력을 받는 경우
12729정성태7/22/202115268.NET Framework: 1080. xUnit 단위 테스트에 메서드/클래스 수준의 문맥 제공 - Fixture
12728정성태7/22/202115294.NET Framework: 1079. MSTestv2 단위 테스트에 메서드/클래스/어셈블리 수준의 문맥 제공
12727정성태7/21/202116473.NET Framework: 1078. C# 단위 테스트 - MSTestv2/NUnit의 Assert.Inconclusive 사용법(?) [1]
12726정성태7/21/202116247VS.NET IDE: 169. 비주얼 스튜디오 - 단위 테스트 선택 시 MSTestv2 외의 xUnit, NUnit 사용법 [1]
12725정성태7/21/202114716오류 유형: 741. Failed to find the "go" binary in either GOROOT() or PATH
12724정성태7/21/202117608개발 환경 구성: 582. 윈도우 환경에서 Visual Studio Code + Go (Zip) 개발 환경 [1]
12723정성태7/21/202114524오류 유형: 740. SharePoint - Alternate access mappings have not been configured 경고
12722정성태7/20/202114276오류 유형: 739. MSVCR110.dll이 없어 exe 실행이 안 되는 경우
12721정성태7/20/202115439오류 유형: 738. The trust relationship between this workstation and the primary domain failed. - 세 번째 이야기
12720정성태7/19/202114692Linux: 43. .NET Core/5+ 응용 프로그램의 Ubuntu (Debian) 패키지 준비
12719정성태7/19/202113906오류 유형: 737. SharePoint 설치 시 "0x800710D8 The object identifier does not represent a valid object." 오류 발생
12718정성태7/19/202113910개발 환경 구성: 581. Windows에서 WSL로 파일 복사 시 root 소유권으로 적용되는 문제파일 다운로드1
12717정성태7/18/202114107Windows: 195. robocopy에서 파일의 ADS(Alternate Data Stream) 정보 복사를 제외하는 방법
12716정성태7/17/202115237개발 환경 구성: 580. msbuild의 Exec Task에 robocopy를 사용하는 방법파일 다운로드1
12715정성태7/17/202122435오류 유형: 736. Windows - MySQL zip 파일 버전의 "mysqld --skip-grant-tables" 실행 시 비정상 종료 [1]
12714정성태7/16/202115797오류 유형: 735. VCRUNTIME140.dll, MSVCP140.dll, VCRUNTIME140.dll, VCRUNTIME140_1.dll이 없어 exe 실행이 안 되는 경우
12713정성태7/16/202117197.NET Framework: 1077. C# - 동기 방식이면서 비동기 규약을 따르게 만드는 Task.FromResult파일 다운로드1
12712정성태7/15/202116111개발 환경 구성: 579. Azure - 리눅스 호스팅의 Site Extension 제작 방법
... 46  47  [48]  49  50  51  52  53  54  55  56  57  58  59  60  ...