Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   TWebBrowser error "Interface not supported" (https://www.clubdelphi.com/foros/showthread.php?t=81170)

kotai 18-10-2012 03:23:35

TWebBrowser error "Interface not supported"
 
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:


Código Delphi [-]
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:

Código Delphi [-]
//******************************************************************************

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.


La franja horaria es GMT +2. Ahora son las 23:58:47.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi