PDA

Ver la Versión Completa : TWebBrowser error "Interface not supported"


kotai
18-10-2012, 03:23:35
Hola.

Tengo un programa que lee el código HTML de una página web y todos sus frames con el componente TWebBrowser. Hace tiempo funcionaba perfectamente, pero ahora lo vuelvo a probar y el código fuente de la página principal lo saca bien, pero cuando va a sacar el de los frames me da un error: EIntfCastError with message "Interface not supported".

Creo que debe ser por la versión de Internet Explorer que ahora tengo la 9 y cuando usaba este programa supongo que tendría la 6 o la 7, pero no estoy seguro si es por eso.

El progama es:


procedure TF_Principal.ObtenerHTML;
var
IpStream : IPersistStreamInit;
AStream : TMemoryStream;
iw : IWebbrowser2;
i : Integer;
sl : TStringList;
OleContainer : IOleContainer;
enum : IEnumUnknown;
unk : IUnknown;
Fetched : System.PLongint;
ss : TStringStream;
sa : IStream;
s : string;
HTML : String;
StreamA : TStreamadapter;
begin
if WB <> nil then
begin
// Obtenemos el HTML de la página principal
WB.Silent := True;
IpStream := WB.Document as IPersistStreamInit;
s := '';
ss := TStringStream.Create(s);
try
sa := TStreamAdapter.Create(ss, soReference) as IStream;
if Succeeded(IpStream.Save(sa, True)) then
HTML := ss.Datastring
else
HTML := '';
finally
ss.Free;
end;
// Analizamos el HTML de la página principal
AnalizarHTML(HTML);
// Obtenemos el HTML de los frames
for i := 0 to WB.OleObject.Document.frames.Length - 1 do
begin
if Assigned(WB.document) then
begin
Fetched := nil;
OleContainer := WB.Document as IOleContainer;
OleContainer.EnumObjects(OLECONTF_EMBEDDINGS, Enum);
Enum.Skip(i);
Enum.Next(1, Unk, Fetched);
try
iw := Unk as IWebbrowser2; **** LINEA DONDE DA EL ERROR *****
except
end;
end;
AStream := TMemoryStream.Create;
IpStream := iw.document as IPersistStreamInit;
StreamA := TStreamadapter.Create(AStream);
if Succeeded(IpStream.save(StreamA, True)) then
begin
AStream.Seek(0, 0);
sl := TStringList.Create;
sl.LoadFromStream(AStream);
AnalizarHTML(sl.Text);
sl.Free;
end;
StreamA.Free;
AStream.Free;
end;
end;
end;



¿ Alguien sabe que puede estar pasando ?

Gracias.

Ñuño Martínez
22-10-2012, 12:28:39
¿Estás usando la misma versión de Delphi? Lo digo porque, si antes funcionaba y ahora no, es posible que hayan cambiado alguna implementación

kotai
22-10-2012, 12:50:53
Si, sigo usando Delphi 2006.

De todas formas ya lo solucioné, importé el ActiveX "Microsoft HTML Object Library" que me hizo un MSHTML_TLB.pas con la clase IHTMLDocument2 que también permite leer el código fuente de los frames:


//******************************************************************************

function GetBrowserForFrame(Doc: IHTMLDocument2; nFrame: Integer): IWebBrowser2;
var
pContainer: IOLEContainer;
enumerator: ActiveX.IEnumUnknown;
nFetched: PLongInt;
unkFrame: IUnknown;
hr: HRESULT;
begin
Result := nil;
nFetched := nil;
// Cast the page as an OLE container
pContainer := Doc as IOleContainer;
// Get an enumerator for the frames on the page
hr := pContainer.EnumObjects(OLECONTF_EMBEDDINGS or OLECONTF_OTHERS, enumerator);
if hr <> S_OK then
begin
pContainer._Release;
Exit;
end;
// Now skip to the frame we're interested in
enumerator.Skip(nFrame);
// and get the frame as IUnknown
enumerator.Next(1,unkFrame, nFetched);
// Now QI the frame for a WebBrowser Interface - I'm not entirely
// sure this is necessary, but COM never ceases to surprise me
unkframe.QueryInterface(IID_IWebBrowser2, Result);
end;

//******************************************************************************

function GetFrameSource(WebDoc: iHTMLDocument2): string;
//returns frame HTML and scripts as a text string
var
re: integer;
HTMLel: iHTMLElement;
HTMLcol: iHTMLElementCollection;
HTMLlen: Integer;
ScriptEL: IHTMLScriptElement;
begin
Result := '';
if Assigned(WebDoc) then
begin
HTMLcol := WebDoc.Get_all;
HTMLlen := HTMLcol.Length;
for re := 0 to HTMLlen - 1 do
begin
HTMLel := HTMLcol.Item(re, 0) as iHTMLElement;
if HTMLEl.tagName = 'HTML' then
Result := Result + HTMLEl.outerHTML;
end;
end;
end;

//******************************************************************************

procedure TF_Principal.ObtenerHTML(Num:SmallInt);
var
Webdoc, HTMLDoc: ihtmldocument2;
framesCol: iHTMLFramesCollection2;
FramesLen: integer;
pickFrame: olevariant;
p: integer;
HTML : String;
iFrame : IWebBrowser2;
begin
if WB <> nil then
try
WebDoc := WB.Document as IHTMLDocument2;
HTML := GetFrameSource(WebDoc);
// analizamos el HTML de la página principal
AnalizarHTML(HTML);
FramesCol := WebDoc.Get_frames;
FramesLen := FramesCol.Get_length;
if FramesLen > 0 then
for p := 0 to FramesLen - 1 do
begin
pickframe := p;
HTMLDoc := WB.Document as iHTMLDocument2;
iFrame := GetBrowserForFrame(HTMLDoc, pickframe);
if iFrame <> nil then
begin
WebDoc := iFrame.document as iHTMLDocument2;
if WebDoc <> nil then
begin
HTML := GetFrameSource(WebDoc);
// analizamos el HTML de este frame
AnalizarHTML(HTML);
end;
end;
end;
except
end;
end;



Saludos.