mshtml.tlb와 같은 형식 라이브러리에서 얻을 수있는 interop 클래스에는 매우 심각한 문제가 있습니다. 형식 라이브러리 임포터는 형식 라이브러리의 coclass 정의에서 synthetic .NET 클래스를 생성합니다. 유형 이름에서 인식 할 수 있으며, "클래스"로 끝나고 인터페이스 유형의 이름으로 시작합니다. 그것들은 COM 클래스가 .NET 클래스 인 것처럼 COM coclass를 처리 할 수 있도록 도와줍니다.
그러나 이는 매우 심각한 버전 문제를 유발합니다. 나는 소스 코드에 mshtml.HtmlHeadElementClass을 마우스 오른쪽 버튼으로 클릭하고 선택하면
[
uuid(3050F493-98B5-11CF-BB82-00AA00BDCE0B),
noncreatable
]
coclass HTMLHeadElement {
[default] dispinterface DispHTMLHeadElement;
[default, source] dispinterface HTMLElementEvents;
[source] dispinterface HTMLElementEvents2;
interface IHTMLElement;
interface IHTMLElement2;
interface IHTMLElement3;
interface IHTMLElement4;
interface IHTMLUniqueName;
interface IHTMLDOMNode;
interface IHTMLDOMNode2;
interface IHTMLElement5;
interface IHTMLDOMConstructor;
interface IHTMLHeadElement;
interface IHTMLHeadElement2;
};
하는 것은 다음 정의로 이동 : 내 컴퓨터에 MSHTML.tlb에보고 oleview.exe을 사용하는 경우 다음 나는 HTMLHeadElement의 coclass에 대한이 정의를 참조 나는 이것을 본다 :
public class HTMLHeadElementClass : DispHTMLHeadElement, HTMLHeadElement,
HTMLElementEvents_Event, IHTMLElement, IHTMLElement2, IHTMLElement3,
IHTMLElement4, IHTMLUniqueName, IHTMLDOMNode, IHTMLDOMNode2,
IHTMLHeadElement, IHTMLElementEvents2_Event {
// Lots of members
//...
}
둘 사이의 불일치에 유의한다. Oleview에서받은 것은 여분의 인터페이스, IHtmlElement5 및 IHtmlHeadElement2입니다. 그 이유는 설명하기 쉽습니다, 나는 내 컴퓨터에 IE9를 설치했습니다. interop 정의는 mshtml PIA에서 가져온 것입니다. 어느 오래된 버전, 아마 IE7 데이트.
새로운 IHtmlElement5 인터페이스가 을 상속 목록에 삽입하여을 삽입했습니다. 이것은 적어도 심각한 오류였습니다. 적어도 .NET 코드가 간다. 순수한 COM 코드는 전혀 중요하지 않습니다.이 인터페이스는 QueryInterface를 사용하여 인터페이스 포인터를 찾아서 코 클라스에 요청합니다. 그러나 은 .NET 래퍼 클래스에 치명적인입니다. IHTMLDOMNode2를 통과 한 모든 메서드에는 잘못된 오프셋이 있습니다. 그래서 IHTMLHeadElement.appendChild 메서드를 호출하면 을 메서드로 잘못 호출하게됩니다.
이것은 해결할 수없는 문제입니다. PIA를 제거하고 자신의 interop.mshtml.dll interop 라이브러리를 생성 할 수 있습니다.이 라이브러리는 컴퓨터에서 올바르게 작동합니다. 그러나 IE9가 설치되지 않은 다른 컴퓨터에서는 제대로 작동하지 않습니다.
사용할 수있는 좋은 해결 방법이 있지만 은 XxxClass 클래스을 사용하지 마십시오. 인터페이스 유형 만 사용하십시오. 어느 (윈폼 응용 프로그램에서 테스트)이 유사한다고 : 그 작은 인터페이스는 항목 요소에 액세스 할 수 이미 충분히 좋은했기 때문에 내가 의도적으로 대신 (IHTMLHeadElement)의 (IHTMLDOMNode)에 캐스트를 사용
var doc = (IHTMLDocument2)webBrowser1.Document.DomDocument;
var headItems = (IHTMLElementCollection)doc.all.tags("head");
var scriptObject = (IHTMLScriptElement)doc.createElement("script");
scriptObject.type = @"text/javascript";
//scriptObject.text = TTS.TTSWebFactory.GetJavascript();
var node = (IHTMLDOMNode)headItems.item(null, 0);
node.appendChild((IHTMLDOMNode)scriptObject);
.