성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
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'> <div style='font-family: 맑은 고딕, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>코드(C#)를 통한 풀 덤프 만드는 방법</div> <br /> 지난번에, '도구'를 통한 풀 덤프 만드는 법을 알아봤지요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > 풀 덤프 파일을 남기는 방법 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/991'>http://www.sysnet.pe.kr/2/0/991</a> </pre> <br /> 도구가 아무리 훌륭해도 역시나 코드를 이용하여 자유롭게 내장하는 것만 못합니다. 일례로, 위의 글에서 살펴본 4가지 방법 모두 자신의 응용 프로그램에 대해 스스로 풀 덤프를 남기길 원할 때 별로 도움이 되지 못합니다. "<a target='_tab' href='https://learn.microsoft.com/ko-kr/windows-hardware/drivers/debugger/debugger-download-tools'>Debugging Tools for Windows</a>"를 설치하는 것도 부담이고 재배포가 안되는 <a target='_tab' href='https://learn.microsoft.com/en-us/sysinternals/downloads/procdump'>Process Dump</a>, 외부 제어 기능이 없는 Task Manager까지... 자신의 응용 프로그램 내부에서 불러다 사용하기에는 하나같이 매끄럽지 않습니다.<br /> <br /> 다행인 점은, 코드를 이용한 풀 덤프를 남기는 방법이 dbghelp.dll의 도움으로 그다지 어렵지 않다는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > MiniDumpWriteDump Function ; <a target='_tab' href='https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump'>https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump</a> </pre> <br /> 단지 제약이라면 dbghelp.dll이 버전 5.1 이상이어야 한다는 점인데요. 그다지 문제라고 할 수 없는 것이, "<a target='_tab' href='https://learn.microsoft.com/ko-kr/windows-hardware/drivers/debugger/debugger-download-tools'>Debugging Tools for Windows</a>"에 포함된 dbghelp.dll 6.x 파일이 재배포가 가능하기 때문입니다. 실제로 redist.txt에 보면 다음과 같이 친절하게 ^^ 안내되어 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > =================== dbghelp.dll =================== (1) You may redistribute <b style='COLOR: blue'>dbghelp.dll version 6.12.2.633</b> </pre> <br /> C#에서도 P/Invoke를 이용해서 쉽게 가져다 쓸 수 있는데 이에 대해서는 다음의 글에서 자세히 설명해 주고 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > How to write out a minidump from try/catch in C#? ; <a target='_tab' href='http://social.msdn.microsoft.com/Forums/is/clr/thread/321f8960-ccbb-49d0-b285-3d2bbf3d20d9'>http://social.msdn.microsoft.com/Forums/is/clr/thread/321f8960-ccbb-49d0-b285-3d2bbf3d20d9</a> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 위의 코드에 대한 사용방법은 매우 간단합니다. 원하는 프로세스 ID에 대해 다음과 같이 System.Diagnostics.Process를 통해 얻어지는 Handle 값을 전달해주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > <b style='COLOR: blue'>Process targetProcess = Process.GetProcessById(processId);</b> using (FileStream stream = new FileStream(dumpFilePath, FileMode.Create)) { Boolean res = MiniDumpWriteDump( <b style='COLOR: blue'>targetProcess.Handle</b>, processId, stream.SafeFileHandle.DangerousGetHandle(), <b style='COLOR: blue'>MiniDumpType.WithFullMemory</b>, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int dumpError = res ? 0 : Marshal.GetLastWin32Error(); Console.WriteLine(dumpError); } </pre> <br /> 그런데, 실제로 해보면 MiniDumpWriteDump API 호출이 FALSE를 반환하고 Marshal.GetLastWin32Error()에서 다음의 값을 반환하는 경우가 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > <b style='COLOR: blue'>0x8007012B (-2147024597)</b> Only part of a ReadProcessMemory or WriteProcessMemory request was completed. </pre> <br /> 이에 대해 검색을 해보면 아래와 같은 답변을 찾을 수 있는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > PROCESS_QUERY_INFORMATION and PROCESS_VM_READ ; <a target='_tab' href='http://forums.whirlpool.net.au/archive/1223530'>http://forums.whirlpool.net.au/archive/1223530</a> you might also have to enable SeDebugPrivilege ; <a target='_tab' href='http://stackoverflow.com/questions/2598615/creating-a-minidump-of-a-running-process'>http://stackoverflow.com/questions/2598615/creating-a-minidump-of-a-running-process</a> </pre> <a name='enable_privilege'></a> <br /> 원인은, "덤프를 뜨려는 프로세스" 측에 "<a target='_tab' href='http://www.sysnet.pe.kr/2/0/95'>SE_DEBUG_NAME</a>" 특권을 가지고 있어야 한다는 것이니, C#에서의 특권 설정에 관해 설명한 다음의 글에 있는 코드를 사용해서 해결할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > C# - How to enable SeDebugPrivilege? ; <a target='_tab' href='http://rongchaua.net/blog/c-how-to-enable-sedebugprivilege/'>http://rongchaua.net/blog/c-how-to-enable-sedebugprivilege/</a> </pre> <a name='bitness'></a> <br /> 위의 방법까지 했는데도 여전히 0x8007012b 오류가 발생할 수 있습니다. 제가 이 부분에서 무척 헤맸었는데요. ^^ 다음의 글에서 원인을 찾을 수 있었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > windbg dump command fails with error 0x8007012b ; <a target='_tab' href='http://stackoverflow.com/questions/842569/windbg-dump-command-fails-with-error-0x8007012b'>http://stackoverflow.com/questions/842569/windbg-dump-command-fails-with-error-0x8007012b</a> </pre> <br /> 즉, x64 운영체제에 한해서 주의를 기울여야 하는데요. "덤프를 뜨는 측의 프로세스"가 32비트이면 "덤프를 뜰 수 있는 대상 프로세스"는 역시 32비트로 제한됩니다. 마찬가지로 이것은 64비트 프로세스에도 그대로 적용됩니다. 따라서, MiniDumpWriteDump로 덤프를 뜨기 전에 대상 프로세스의 플랫폼 타입을 알아보고 그에 맞는 덤프 프로세스를 구동시켜야 합니다. 이는, 다음의 IsWow64Process Win32 API를 사용하는 것으로 해결할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process([In] IntPtr processHandle, [Out, MarshalAs(UnmanagedType.Bool)] out bool wow64Process); </pre> <br /> 마지막으로, ^^ 이렇게까지 했는데도,,, 여전히 덤프오류가 발생할 수 있습니다. 특정 프로세스에 한해서 그런 일이 발생하는데요. 가만히 살펴보면, Vista/7 이상의 운영체제에서 시스템 권한의 프로세스들에 대해 덤프를 뜨려 할 때 발생하는 것을 볼 수 있습니다. 즉, 이 때문에 모든 프로세스에 대해 자유롭게 덤프를 뜨고 싶다면 "덤프를 뜨는 측의 프로세스"를 "관리자 권한"으로 실행시켜야 합니다. 이 부분은 예전에 알려드린 방법을 사용하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > ClickOnce - 관리자 권한 상승하는 방법 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/950'>http://www.sysnet.pe.kr/2/0/950</a> </pre> <br /> 최종적으로 이런 모든 사항을 적용하여 간단하게 덤프를 뜨는 프로그램을 만들어보았습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > MinidumpWriter ; <a target='_tab' href='http://www.sysnet.pe.kr/temp/app/dumpwriter/MinidumpWriter.application'>http://www.sysnet.pe.kr/temp/app/dumpwriter/MinidumpWriter.application</a> </pre> <br /> <img alt='sysnet_dumpwriter_1.png' onclick='toggle_img(this)' class='imgView' src='/SysWebRes/bbs/sysnet_dumpwriter_1.png' /><br /> <br /><br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8986
(왼쪽의 숫자를 입력해야 합니다.)