성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
닷넷
.NET 3.0
.NET 3.5
.NET 4.0
VC++
개발 환경 구성
제품 소개
VS.NET IDE
Vista
Windows 7
Windows 8
Windows 서버
Team Foundation Server
IIS
디버깅 기술
Win32
64비트
오피스
웹
기타
Phone
부모글 보이기/감추기
내용
[출처] <a target="_blank" href="https://docs.microsoft.com/en-us/archive/blogs/jmstall/how-to-get-a-v2-0-icordebug-object">https://docs.microsoft.com/en-us/archive/blogs/jmstall/how-to-get-a-v2-0-icordebug-object</a><br /> <br /> 결국 "온고지신"이라는 말이 떠오릅니다.<br /> COM과 Win32 API는 보이지만 않게 될 뿐, 여전히 하부에서 존재하고 있습니다.<br /> <br /> <hr /> <H2>How to get a V2.0 ICorDebug object</H2> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">I think the biggest breaking change in the ICorDebug API is how we deal with versioning.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">Managed debugging is done via the com-classic ICorDebug interface. </P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">In v1.0/v1.1, you cocreate to get an ICorDebug implementation, like so:</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>ICorDebug * cor; <o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>hr = <B style="mso-bidi-font-weight: normal">CoCreateInstance</B>(<B style="mso-bidi-font-weight: normal">CLSID_CorDebug</B>, NULL, <o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>CLSCTX_INPROC_SERVER, <o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>IID_ICorDebug,<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>(<SPAN style="COLOR: blue">void</SPAN> **)&cor);<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">This has a few problems:</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2; tab-stops: list .5in"><SPAN style="mso-list: Ignore">-<SPAN style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN>COM activation is evil because it means a more complex setup to update the registry. This allows bugs like “you need to reregister mscordbi.dll”. A quick <A href="http://www.google.com/search hl=en&q=register+mscordbi">google search</A> shows that people hit this problem enough.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo2; tab-stops: list .5in"><SPAN style="mso-list: Ignore">-<SPAN style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN>there are no version parameters in here</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">In v2.0, there is no longer a com coclass for ICorDebug. We still use the com-class ICorDebug interfaces, but we don’t use COM activation anymore. You now call a new API defined in mscoree.idl:</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">STDAPI CreateDebuggingInterfaceFromVersion(<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">int iDebuggerVersion,<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">LPCWSTR szDebuggeeVersion,<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">IUnknown ** ppCordb);<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">This takes version parameters. iDebuggerVersion is a constant from CorDebug.idl specifying the version of the API the client is built against.<SPAN style="mso-spacerun: yes"> </SPAN>szDebuggeeVersion is the version string of the debuggee.<SPAN style="mso-spacerun: yes"> </SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">*ppCordb is an out parameter for the newly allocated com-object.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">Here’s some sample code to use the new API:</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: green">// Sample code to get an ICorDebug instance to debug v1.1.<o:p></o:p></SPAN></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">typedef</SPAN> HRESULT (STDAPICALLTYPE *FPCreateCordb)(<SPAN style="COLOR: blue">int</SPAN> iDebuggerVersion, LPCWSTR szDebuggeeVersion, IUnknown ** ppCordb);<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><o:p> </o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: green">// Must late bind to CreateDebuggingInterfaceFromVersion since it may not be installed.</SPAN><o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>HMODULE hMscoree = LoadLibraryA("mscoree.dll");<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">if</SPAN> (hMscoree == null) { <SPAN style="COLOR: green">/* Serious error, v2.0 runtime is not installed! */ }</SPAN><o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>FPCreateCordb fpCreateCordb = (FPCreateCordb) GetProcAddress(m_hMscoree, "<B style="mso-bidi-font-weight: normal">CreateDebuggingInterfaceFromVersion</B>");<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">if</SPAN> (fpCreateCordb == NULL) {<SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: green">/* fail */</SPAN> }<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><o:p> </o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">const char</SPAN> * szDebuggeeVersion = “v1.1.4322”; <SPAN style="COLOR: green">// if we’re debugging a v1.1 debuggee </SPAN><o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">const int</SPAN> iDebuggerVersion = CorDebugVersion_2_0; <SPAN style="COLOR: green">// if we’re a v2.0 debugger.</SPAN><o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>hr = <B style="mso-bidi-font-weight: normal">fpCreateCordb(CorDebugVersion_2_0, szEverettVersion, &pObject)</B>;<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">if</SPAN> (FAILED(hr)) { <SPAN style="COLOR: green">/* fail */</SPAN> }<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><o:p> </o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>ICorDebug * cor;<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN>hr = pObject->QueryInterface(IID_ICorDebug, (<SPAN style="COLOR: blue">void</SPAN>**) &cor);<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes"> </SPAN><SPAN style="COLOR: blue">if</SPAN> (FAILED(hr)) { <SPAN style="COLOR: green">/* fail */</SPAN> }<o:p></o:p></SPAN></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">Note that <A title="" href="/jmstall/archive/2004/09/30/236281.aspx">MDbg</A> in the beta 1 sample is still using the old API, but we’ve updated it in the beta2 release.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><B style="mso-bidi-font-weight: normal">Why the change?<o:p></o:p></B></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">The debugging services in V1 didn’t have a good versioning plan. The original idea was that the debugger would just create a single instance of ICorDebug (via CoCreate) and that would emulate all other versions as needed. </P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">This was a bad idea.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">That means if you have an v1 debugger on a v1 debuggee, you’ll use the v1 implementation of ICorDebug. As soon as you install a v2 CLR, that scenario is automatically updated to use a V2 implementation of ICorDebug.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">If that new implementation doesn’t perfectly emulate the old one, then the mere act of installing a new v2 runtime would have broken a pure v1 scenario. </P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">The test matrix also explodes very quickly. We’d have to test every version against every previous version. </P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">ICorDebug design flaws also prevent us from shimming implementations underneath the interface either. We don’t know the version of the debuggee until a CreateProcess callback is dispatched, but there’s still a lot of functionality before that callback (including interop-debugging support).</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">We concluded the only viable alternative was to keep 1 version of the ICorDebug implementation<SPAN style="mso-spacerun: yes"> </SPAN>per CLR. With the new APIs, installing a new CLR does not have any impact on the what happens to the debugging pipeline of existing apps. You’ll also notice now that the version of mscordbi.dll in the debugger will always strictly match the version of mscorwks.dll in the debuggee. So when a v2.0 debugger is debugging a v1.0 application, it loads the v1.0 mscordbi. (Unfortunately, this will be a problem for debuggers implemented in managed code. See <A href="http://blogs.msdn.com/jmstall/archive/2004/11/02/250946.aspx">here</A> for details.).</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">This ugliness is an example of the consequence of not really thinking about versioning until v2.0.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><B style="mso-bidi-font-weight: normal">Issues with the new design:<o:p></o:p></B></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">The biggest immediate problem with the new design is where do you get the debuggee’s version string from? The debugger needs to predict the debuggee’s version before it launches it. There are a few APIs in mscoree.idl to help with this:</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1; tab-stops: list .5in"><SPAN style="mso-list: Ignore">1)<SPAN style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN><A href="http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpgenref/html/grfungetcorversion.asp">GetCORVersion</A> this will get the version string for the currently executing process. This works fine if the debugger + debuggee have the same version. (This is what beta 1 <A title="" href="/jmstall/archive/2004/09/30/236281.aspx">MDbg</A> does.)</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1; tab-stops: list .5in"><SPAN style="mso-list: Ignore">2)<SPAN style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN>GetRequestedRuntimeVersion this predict the version string from an executable on disk based off policy settings, config files, etc. This will always be accurate for a pure-managed app like C#.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1; tab-stops: list .5in"><SPAN style="mso-list: Ignore">3)<SPAN style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN>GetVersionFromProcess this will find the version string from a currently running process. This API was added in v2.0 to explicitly support this scenario.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">There are of course cases where there’s no way to predict the version string. Consider a pure native app that pops up a dialog box asking the user which runtime to bind to and then calls <A href="http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpgenref/html/grfuncorbindtoruntimeex.asp">CorBindToRuntimeEx</A> on the fly.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">All this said, we considered these limitations doable given the scenarios we wanted to support. </P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p> </o:p></P> <DIV class=postfoot>Published Saturday, January 15, 2005 5:02 PM by <A id=_ctl0____ctl0____ctl1___Entry___AuthorLink href="/user/Profile.aspx UserID=4072">jmstall</A> <BR>Filed Under: <A id=_ctl0____ctl0____ctl1___Entry___Tags___Categories__ctl1_Link href="http://blogs.msdn.com/jmstall/archive/category/7367.aspx" rel=tag>ICorDebug</A>, <A id=_ctl0____ctl0____ctl1___Entry___Tags___Categories__ctl3_Link href="http://blogs.msdn.com/jmstall/archive/category/8639.aspx" rel=tag>Whidbey (V2.0)</A>
첨부파일
스팸 방지용 인증 번호
1872
(왼쪽의 숫자를 입력해야 합니다.)