성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>guidgen - Encountered an improper argument. 오류 해결 방법 (및 windbg 분석)</h1> <p> Visual Studio의 guidgen을 실행했는데, "Encountered an improper argument." 오류 메시지만 발생하고 GUID 값 출력이 안 되는 경우가 있습니다. 현상을 자세히 관찰해 보면 guidgen 실행 화면의,<br /> <br /> <img width='290' alt='guidgen_not_work_1.png' src='/SysWebRes/bbs/guidgen_not_work_1.png' /><br /> <br /> Radio button을 누를 때마다 "Encountered an improper argument." 메시지가 발생하는 것을 확인할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 검색해 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Fixing erroneous GUID creation in Visual Studio 2010 ; <a target='tab' href='https://modery.net/fixing-erroneous-guid-creation-in-visual-studio-2010/'>https://modery.net/fixing-erroneous-guid-creation-in-visual-studio-2010/</a> </pre> <br /> 예전 버전을 쓰라고 나오는데, 그것보다는 그냥 새롭게 확장 프로그램을 설치하는 것이 더 좋을 수도 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > GuidGen 2.0 ; <a target='tab' href='https://marketplace.visualstudio.com/items?itemName=AndrewLArnott.GuidGen20'>https://marketplace.visualstudio.com/items?itemName=AndrewLArnott.GuidGen20</a> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 일단, 문제 해결(?)은 되었는데 그래도 왜 그런 문제가 발생했는지 궁금합니다. ^^ 그래서 windbg를 통해 GUID를 생성하는 Win32 API에 bp를 걸고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > bp rpcrt4!UuidCreate </pre> <br /> 추적했을 때 RPCRT4!_imp__ProcessPrng 호출에 넘겨준 인자(esi)가,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > RPCRT4!UuidCreate: 750ec790 8bff mov edi,edi 750ec792 55 push ebp 750ec793 8bec mov ebp,esp 750ec795 56 push esi 750ec796 8b7508 mov esi,dword ptr [ebp+8] 750ec799 6a10 push 10h 750ec79b 56 <span style='color: blue; font-weight: bold'>push esi</span> 750ec79c ff1594f01575 <span style='color: blue; font-weight: bold'>call dword ptr [RPCRT4!_imp__ProcessPrng (7515f094)]</span> </pre> <br /> 호출 전에는 0x10h 길이의 빈 버퍼였다가,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>db @esi Lf</span> 00d3fb30 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 ............... </pre> <br /> 호출 후에는 정상적으로 GUID 값이 들어온 것을 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>db @esi Lf</span> 00d3fb30 1c 79 31 15 d8 e0 58 31-dc 2f 74 a7 fe c8 62 .y1...X1./t...b </pre> <br /> 따라서 GUID 생성 자체에는 아무런 문제가 없었습니다. 이후 문제가 되는 코드를 추적해 보면, GuidGen!CGuidGenDlg::GetFormattedGuid 호출에서 C++ 예외가 발생하는 현상을 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> u GuidGen!CGuidGenDlg::OnChangedSel+0x29: 00c325ce e8ea000000 <span style='color: blue; font-weight: bold'>call GuidGen!CGuidGenDlg::GetFormattedGuid (00c326bd)</span> 00c325d3 ff75f0 push dword ptr [ebp-10h] 00c325d6 8bce mov ecx,esi 00c325d8 684c040000 push 44Ch 00c325dd ff15e451c300 call dword ptr [GuidGen!_imp_?SetDlgItemTextWCWndQAEXHPB_WZ (00c351e4)] 00c325e3 8d4df0 lea ecx,[ebp-10h] 00c325e6 ff153c53c300 call dword ptr [GuidGen!_imp_??1?$CStringT_WV?$StrTraitMFC_DLL_WV?$ChTraitsCRT_WATLATLQAEXZ (00c3533c)] 00c325ec e81b140000 call GuidGen!_EH_epilog3 (00c33a0c) 0:000> <span style='color: blue; font-weight: bold'>p</span> (830.67a8): <span style='color: blue; font-weight: bold'>C++ EH exception - code e06d7363 (first chance)</span> ModLoad: 552b0000 55303000 C:\WINDOWS\SysWOW64\Oleacc.dll ModLoad: 76410000 76494000 C:\WINDOWS\SysWOW64\SHCORE.dll </pre> <br /> 희망이 보이는군요. ^^ bp를 다시 잡고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > bp GuidGen!CGuidGenDlg::GetFormattedGuid </pre> <br /> restart로 추적하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>uf GuidGen!CGuidGenDlg::GetFormattedGuid</span> GuidGen!CGuidGenDlg::GetFormattedGuid: 00c326bd 6a20 push 20h 00c326bf b84d3cc300 mov eax,offset GuidGen!memcpy+0xdb (00c33c4d) 00c326c4 e869130000 call GuidGen!_EH_prolog3 (00c33a32) 00c326c9 8bd9 mov ebx,ecx 00c326cb 895df0 mov dword ptr [ebp-10h],ebx 00c326ce 8d4dec lea ecx,[ebp-14h] 00c326d1 ff15d853c300 call dword ptr [GuidGen!_imp_??0?$CStringT_WV?$StrTraitMFC_DLL_WV?$ChTraitsCRT_WATLATLQAEXZ (00c353d8)] 00c326d7 8365fc00 and dword ptr [ebp-4],0 00c326db 8d4dec lea ecx,[ebp-14h] 00c326de 8b83a8000000 mov eax,dword ptr [ebx+0A8h] 00c326e4 83c068 add eax,68h 00c326e7 50 push eax <span style='color: blue; font-weight: bold'>00c326e8 ff15c851c300 call dword ptr [GuidGen!_imp_?LoadStringW?$CStringT_WV?$StrTraitMFC_DLL_WV?$ChTraitsCRT_WATLATLQAEHIZ (00c351c8)]</span> 00c326ee 85c0 test eax,eax 00c326f0 7506 jne GuidGen!CGuidGenDlg::GetFormattedGuid+0x3b (00c326f8) Branch GuidGen!CGuidGenDlg::GetFormattedGuid+0x35: 00c326f2 ff15cc51c300 call dword ptr [GuidGen!_imp_?AfxThrowInvalidArgExceptionYGXXZ (00c351cc)] GuidGen!CGuidGenDlg::GetFormattedGuid+0x3b: 00c326f8 0fb683bf000000 movzx eax,byte ptr [ebx+0BFh] ...[생략]... 00c327b2 c20400 ret 4 </pre> <br /> 다시 "call dword ptr [GuidGen!_imp_?LoadStringW?<span class="tex2jax_ignore">$</span>CStringT_WV?<span class="tex2jax_ignore">$</span>StrTraitMFC_DLL_WV?<span class="tex2jax_ignore">$</span>ChTraitsCRT_WATLATLQAEHIZ" 코드로 문제를 좁힐 수 있고, 그 함수에 진입해 살펴보면, <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:000> <span style='color: blue; font-weight: bold'>uf @eip</span> mfc140u!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::LoadStringW [d:\agent\_work\3\s\src\vctools\vc7libs\ship\atlmfc\include\cstringt.h @ 2330]: 2330 5a8742a0 55 push ebp 2330 5a8742a1 8bec mov ebp,esp 2330 5a8742a3 56 push esi 2331 5a8742a4 ff7508 push dword ptr [ebp+8] 2330 5a8742a7 8bf1 mov esi,ecx 2331 5a8742a9 e8b283ffff <span style='color: blue; font-weight: bold'>call mfc140u!AfxFindStringResourceHandle (5a86c660) // bp mfc140u!AfxFindStringResourceHandle 2332 5a8742ae 85c0 test eax,eax</span> 2332 5a8742b0 740b je mfc140u!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::LoadStringW+0x1d (5a8742bd) Branch mfc140u!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::LoadStringW+0x12 [d:\agent\_work\3\s\src\vctools\vc7libs\ship\atlmfc\include\cstringt.h @ 2337]: 2337 5a8742b2 ff7508 push dword ptr [ebp+8] 2337 5a8742b5 8bce mov ecx,esi 2337 5a8742b7 50 push eax 2337 5a8742b8 e813000000 call mfc140u!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::LoadStringW (5a8742d0) mfc140u!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::LoadStringW+0x1d [d:\agent\_work\3\s\src\vctools\vc7libs\ship\atlmfc\include\cstringt.h @ 2337]: 2337 5a8742bd 5e pop esi 2338 5a8742be 5d pop ebp 2338 5a8742bf c20400 ret 4 </pre> <br /> AfxFindStringResourceHandle의 반환값(eax)이 null로 나오는 것을 확인할 수 있습니다. 혹시나 싶어서 guidgen.exe가 정상적으로 동작하는 PC에서 위의 과정을 살펴보니 AfxFindStringResourceHandle이 반환하는 값은 다음의 경로에 해당하는 DLL의 로딩 주소였습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\<span style='color: blue; font-weight: bold'>1033</span>\guidgenui.dll </pre> <br /> 그러고 보니, 문제가 발생한 PC의 경우에는 한글 비주얼 스튜디오가 설치되어 있었고 locale에 따라 1042 폴더 하위에 마찬가지로 guidgenui.dll 파일이 놓여 있었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\<span style='color: blue; font-weight: bold'>1042</span>\guidgenui.dll </pre> <br /> 하지만, 정작 guidgen.exe가 실행되었을 때는 guidgenui.dll 파일을 1042로부터 로딩을 하지 않았습니다. 혹시나 싶어서 ^^ 기존의 "1042" 폴더를 그대로 "1033"으로 복사해 실행해 봤더니,<br /> <br /> <img width='290' alt='guidgen_not_work_2.png' src='/SysWebRes/bbs/guidgen_not_work_2.png' /><br /> <br /> 아주 잘 실행이 되는군요.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그러니까, 문제의 원인은 guidgen.exe가 다국어 지원을 하는 환경은 갖췄지만 정작 코드에서는 영문 locale만을 대상으로 동작하는 버그를 갖고 있던 것입니다. 그렇다 해도 여전히 이해가 안 되는 부분이 있습니다. 일반적으로 다국어 지원은 해당 언어가 없을 때 fallback 차원에서 EXE 스스로 들고 있는 중립 리소스를 사용하는 것이 관례입니다.<br /> <br /> 실제로 guidgen.exe의 리소스 영역을 열어 보면 String Resource가 마련되어 있고 guidgenui.dll과 동일한 리소스 ID의 값들을 가지고 있습니다. 암튼, 문제 분석은 여기까지 하는 걸로. ^^<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1244
(왼쪽의 숫자를 입력해야 합니다.)