IE Interop MSHTML
9 отговора
257 прегледа
IE Interop MSHTML
(Предварително се извинявам, че не описвам достатъчно ясно, но и на мен самият не ми е съвсем ясно :)) )
(platform : .NET C#)
Значи в обикновена WinForm-а слагам Web Browser Control. В него зареждам някакъв html документ. Искам да го манипулирам с MSHTML обект.
Add-вам reference към MSHTML и правя в кода :
HTMLDocument doc = new HTMLDocumentClass () ;
doc = (HTMLDocument) axWebBrowser1.Document ;
(Където axWebBrowser1 е името на Web Browser Control-а, който ползвам)
Дотук всичко е перфектно.
Сега искам да си взема детеВъзли
(childNodes) на този doc.
Из MSDN-а чета ей такива неща
HRESULT IHTMLDocument3::get_childNodes(IDispatch **p);
и оттук оттам прихващам, че трябва да се прави QueryInterface през някакъв IDispach и т.н. неща, които незнам как да ползвам ....
Целта ми е да взема childNodes във някакъв обикновен .Net collection - Array Array list и т.н. каквото и да е .... за да мога да работя с тези nodes.
Предполагам, че ако се пробвам да достъпя определен метод на някой Node ще имам подобен проблем ...
Ако някой знае как се прави моля да помогне !
sunsande
(platform : .NET C#)
Значи в обикновена WinForm-а слагам Web Browser Control. В него зареждам някакъв html документ. Искам да го манипулирам с MSHTML обект.
Add-вам reference към MSHTML и правя в кода :
HTMLDocument doc = new HTMLDocumentClass () ;
doc = (HTMLDocument) axWebBrowser1.Document ;
(Където axWebBrowser1 е името на Web Browser Control-а, който ползвам)
Дотук всичко е перфектно.
Сега искам да си взема детеВъзли
Из MSDN-а чета ей такива неща
HRESULT IHTMLDocument3::get_childNodes(IDispatch **p);
и оттук оттам прихващам, че трябва да се прави QueryInterface през някакъв IDispach и т.н. неща, които незнам как да ползвам ....
Целта ми е да взема childNodes във някакъв обикновен .Net collection - Array Array list и т.н. каквото и да е .... за да мога да работя с тези nodes.
Предполагам, че ако се пробвам да достъпя определен метод на някой Node ще имам подобен проблем ...
Ако някой знае как се прави моля да помогне !
sunsande
Re: IE Interop MSHTML
супер лесно е ... това което ти четеш е API документация ...
HTMLDocument doc = (HTMLDocument) axWebBrowser1.Document ;
foreach(HtmlNode node in doc.ChildNodes)
{
processNode( node );
}
XM TurboCT .. where comfort meets power
HTMLDocument doc = (HTMLDocument) axWebBrowser1.Document ;
foreach(HtmlNode node in doc.ChildNodes)
{
processNode( node );
}
XM TurboCT .. where comfort meets power
Re: IE Interop MSHTML
Werno li be :) ?
leleee az sym perkulqsal - sega shte ida da probwam - znaeh si che w petyk wecher ne stawam za nishto :)
Blagodarsko !
sunsande
leleee az sym perkulqsal - sega shte ida da probwam - znaeh si che w petyk wecher ne stawam za nishto :)
Blagodarsko !
sunsande
maj nqma da e lesno :( ...
Привет
Явно с foreach има проблем при interop ... не разбирам много, но знам че от COM към managed code и обратното е много важно да се преобразуват данните в подходящите за съответната технолгия формати.
childNodes колекцията на практика не е колекция за .NET-а ... малко refresh на паметта и се сетих, че foreach може да се използва само ако тази колекция имплементира IEnumerable интерфейс (има GetEnumerator метод).
childNodes очевидно няма - при compile получавам :
... Form1.cs(166): foreach statement cannot operate on variables of type 'object' because 'object' does not contain a definition for 'GetEnumerator', or it is inaccessible
... и след мъглата .... мъгла ...
sunsande
Явно с foreach има проблем при interop ... не разбирам много, но знам че от COM към managed code и обратното е много важно да се преобразуват данните в подходящите за съответната технолгия формати.
childNodes колекцията на практика не е колекция за .NET-а ... малко refresh на паметта и се сетих, че foreach може да се използва само ако тази колекция имплементира IEnumerable интерфейс (има GetEnumerator метод).
childNodes очевидно няма - при compile получавам :
... Form1.cs(166): foreach statement cannot operate on variables of type 'object' because 'object' does not contain a definition for 'GetEnumerator', or it is inaccessible
... и след мъглата .... мъгла ...
sunsande
и още нещо към шефа на Соди :)
в псевдо кода който прати има тип HTMLNode ... на практика в MSHTML няма такъв - има интерфейс IHTMLDomNode ....
(не че използването му променя нещо ...)
BTW ако наистина си ползвал по подобен начин childNodes или друга колекция през interop можеш ли да пратиш малко код ?
Благодаря предварително
sunsande
(не че използването му променя нещо ...)
BTW ако наистина си ползвал по подобен начин childNodes или друга колекция през interop можеш ли да пратиш малко код ?
Благодаря предварително
sunsande
Re: и още нещо към шефа на Соди :)
не си импортнал правилно web control-ата ...
има много начини да направиш това ...
1) можеш да си генерираш ActiveX wrapper за shdocvw като ползваш aximp. Правиш това от командния промпт:
aximp c:\windows\system32\shdocvw.dll
Това ще ти генерира 2 асемблита:
Generated Assembly: SHDocVw.dll
Generated Assembly: AxSHDocVw.dll
Сега вече можеш да ползваш тия асемблита в проекта си и да ползваш AxWebBrowser.
2) Може и без да генерираш ActiveX wrapper. Така няма да ти се налага да distribute shdocvw.dll и axshdocvw.dll. Просто наследяваш AxHost и си attach твой собствен IWebBrowserEvents interface като override-ваш CreateSink, AttachInterfaces и DetachSink.
Всички интерфейси можеш да ги ползваш като импортнеш type library dll C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll
Трябва да ти се генерира нещо такова:
[
Guid(@"3050F485-98B5-11CF-BB82-00AA00BDCE0B"),
TypeLibType(TypeLibTypeFlags.FDispatchable|TypeLibTypeFlags.FDual)
]
public interface IHTMLDocument3 : IHTMLDocument2
{
[DispId(1072 /*0x0430*/)]
void releaseCapture();
[DispId(1073 /*0x0431*/)]
void recalc(bool fForce);
[DispId(1074 /*0x0432*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object createTextNode(string text);
[DispId(1075 /*0x0433*/)]
IHTMLElement documentElement
{
[return: MarshalAs(UnmanagedType.Interface)] get; }
[DispId(1077 /*0x0435*/)]
string uniqueID
{
[return: MarshalAs(UnmanagedType.BStr)] get; }
[DispId(-2147417605 /*0x800101FB*/)]
bool attachEvent(string _event, object pdisp);
[DispId(-2147417604 /*0x800101FC*/)]
void detachEvent(string _event, object pdisp);
. . . . . .
и така нататък . . .
а за ChildNodes си прав ... просто трябва да го cast първо ... мисля че беше HtmlNodesCollection ... ето малко код:
HtmlNodeCollection forms = doc.DocumentNode.SelectNodes("//form");
foreach( HtmlNode formNode in forms )
{
HtmlNodeCollection inputControls = formNode.SelectNodes(".//input");
foreach( HtmlNode inputControl in inputControls )
{
...
}
}
успех
XM TurboCT .. where comfort meets power
има много начини да направиш това ...
1) можеш да си генерираш ActiveX wrapper за shdocvw като ползваш aximp. Правиш това от командния промпт:
aximp c:\windows\system32\shdocvw.dll
Това ще ти генерира 2 асемблита:
Generated Assembly: SHDocVw.dll
Generated Assembly: AxSHDocVw.dll
Сега вече можеш да ползваш тия асемблита в проекта си и да ползваш AxWebBrowser.
2) Може и без да генерираш ActiveX wrapper. Така няма да ти се налага да distribute shdocvw.dll и axshdocvw.dll. Просто наследяваш AxHost и си attach твой собствен IWebBrowserEvents interface като override-ваш CreateSink, AttachInterfaces и DetachSink.
Всички интерфейси можеш да ги ползваш като импортнеш type library dll C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll
Трябва да ти се генерира нещо такова:
[
Guid(@"3050F485-98B5-11CF-BB82-00AA00BDCE0B"),
TypeLibType(TypeLibTypeFlags.FDispatchable|TypeLibTypeFlags.FDual)
]
public interface IHTMLDocument3 : IHTMLDocument2
{
[DispId(1072 /*0x0430*/)]
void releaseCapture();
[DispId(1073 /*0x0431*/)]
void recalc(bool fForce);
[DispId(1074 /*0x0432*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object createTextNode(string text);
[DispId(1075 /*0x0433*/)]
IHTMLElement documentElement
{
[return: MarshalAs(UnmanagedType.Interface)] get; }
[DispId(1077 /*0x0435*/)]
string uniqueID
{
[return: MarshalAs(UnmanagedType.BStr)] get; }
[DispId(-2147417605 /*0x800101FB*/)]
bool attachEvent(string _event, object pdisp);
[DispId(-2147417604 /*0x800101FC*/)]
void detachEvent(string _event, object pdisp);
. . . . . .
и така нататък . . .
а за ChildNodes си прав ... просто трябва да го cast първо ... мисля че беше HtmlNodesCollection ... ето малко код:
HtmlNodeCollection forms = doc.DocumentNode.SelectNodes("//form");
foreach( HtmlNode formNode in forms )
{
HtmlNodeCollection inputControls = formNode.SelectNodes(".//input");
foreach( HtmlNode inputControl in inputControls )
{
...
}
}
успех
XM TurboCT .. where comfort meets power
Re: и още нещо към шефа на Соди :)
Uha :) shwanah gore dolu ideqta, no shte ima da porabotq nad towa :) ...
Blagodarq mnogo !
sunsande
Blagodarq mnogo !
sunsande
тъп въпрос ...
1) C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll
това е .NЕТ assembly защо му е необходим type library import ?
2) Това ми е copy/paste ot console-ата
C:\Program Files\Microsoft.NET\Primary Interop Assemblies>TlbImp Microsoft.mshtml.dll /out:Microsoft.mshtml.RCW.dll
Microsoft (R) .NET Framework Type Library to Assembly Converter 1.1.4322.573
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.
TlbImp error: The input file 'C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll'
is not a valid type library
Аналогичен резултат получавам и при опит за импорт на
C:\WINNT\system32\mshtml.dll (който е ActiveX)
и нямам идея как да направя този import.
***
BTW ръчках малко и открих следното
ако направя
doc = (HTMLDocument) axWebBrowser1.Document ;
doc.forms.length ми връща int и мога да си итерирам doc.forms с foreach
Но doc.childNodes.length го няма, както и doc.baseUrl за което вдига exception "Not implemented" ...
Това ме наведе на мисълта да разгледам къде са имплементирани тия methods и properties ... E doc.forms си го има във IHTMLDocument, а doc.childNodes и doc.baseUrl са в IHTMLDocument3 ...
Незнам обаче как да си поискам от axWebBrowser да ми даде IHTMLDocument3 вместо само IHTMLDocument
sunsande
и след мъглата ...
това е .NЕТ assembly защо му е необходим type library import ?
2) Това ми е copy/paste ot console-ата
C:\Program Files\Microsoft.NET\Primary Interop Assemblies>TlbImp Microsoft.mshtml.dll /out:Microsoft.mshtml.RCW.dll
Microsoft (R) .NET Framework Type Library to Assembly Converter 1.1.4322.573
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.
TlbImp error: The input file 'C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll'
is not a valid type library
Аналогичен резултат получавам и при опит за импорт на
C:\WINNT\system32\mshtml.dll (който е ActiveX)
и нямам идея как да направя този import.
***
BTW ръчках малко и открих следното
ако направя
doc = (HTMLDocument) axWebBrowser1.Document ;
doc.forms.length ми връща int и мога да си итерирам doc.forms с foreach
Но doc.childNodes.length го няма, както и doc.baseUrl за което вдига exception "Not implemented" ...
Това ме наведе на мисълта да разгледам къде са имплементирани тия methods и properties ... E doc.forms си го има във IHTMLDocument, а doc.childNodes и doc.baseUrl са в IHTMLDocument3 ...
Незнам обаче как да си поискам от axWebBrowser да ми даде IHTMLDocument3 вместо само IHTMLDocument
sunsande
и след мъглата ...
решение
(извинявам се за многото posts)
...
private AxSHDocVw.AxWebBrowser axWebBrowser1; //директно се добавя от toolbar-a
...
IHTMLDocument3 doc = (IHTMLDocument3) axWebBrowser1.Document ;
//3 е за да има childNodes
IHTMLDOMChildrenCollection nodes = (IHTMLDOMChildrenCollection)doc.childNodes ;
foreach (IHTMLDOMNode n in nodes)
{
//Use n as you wish
}
childNоdes се cast-ва само с IHTMLDOMChildrenCollection (4-5 часа ровене докато открия :((( )
sunsande
...
private AxSHDocVw.AxWebBrowser axWebBrowser1; //директно се добавя от toolbar-a
...
IHTMLDocument3 doc = (IHTMLDocument3) axWebBrowser1.Document ;
//3 е за да има childNodes
IHTMLDOMChildrenCollection nodes = (IHTMLDOMChildrenCollection)doc.childNodes ;
foreach (IHTMLDOMNode n in nodes)
{
//Use n as you wish
}
childNоdes се cast-ва само с IHTMLDOMChildrenCollection (4-5 часа ровене докато открия :((( )
sunsande