Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Problema con WebBrowser. Uno más. (https://www.clubdelphi.com/foros/showthread.php?t=87879)

Jontart 11-03-2015 22:01:04

Problema con WebBrowser. Uno más.
 
Saludos cordiales,

hace bastante tiempo que no entro por aquí, y que no uso delphi, por lo que estoy bastante perdido.
Tengo un problema con un TWebBrowser, a la hora de mandar información a una página web por código.

Al pulsar un TButtom, meto la dirección de una página web, introduzco el usuario y el password que me piden y valido. Sin problemas.
Al pulsar un segundo TButtom, me dirigo a un link determinado de la página anterior. Sin problemas.
Al pulsar un tercer TButtom, edito un TEXAREA y hago un SUBMIT al servidor. También sin problemas.

El PROBLEMA está cuando intento hacerlo todo seguido, sin recurrir a los TButtom.

Código Delphi:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
Var
   ovElemento: OleVariant;
begin
// Cargo la página en cuestión
  WebBrowser1.Navigate('direccion pagina web');

// Espero a que esté totalmente cargada
   while webBrowser1.ReadyState < READYSTATE_INTERACTIVE do  Application.ProcessMessages;

// Doy valores a los elementos CONOCIDOS que me interesan
   ovElemento := WebBrowser1.OleObject.Document.forms.item(0).elements;

   ovElemento.item(1).value:='usuario';        // Escribe en la página el usuario
   ovElemento.item(2).value:='contraseña';  // Escribe en la página la password
   ovElemento.item(3).click;                      // Mandamos al servidor la información

end;

procedure TForm1.Button2Click(Sender: TObject);
Var
   ovElemento: OleVariant;
begin
   ovElemento:= WebBrowser1.OleObject.Document.links;
   ovElemento.item(38).click;  // Conozco el item que me interesa. No necesito buscarlo.
end;

procedure TForm1.Button3Click(Sender: TObject);
Var
   ovElemento: OleVariant;
begin
    ovElemento := WebBrowser1.OleObject.Document.forms.item(1).elements;

   ovElemento.item(2).value := 'Texto a enviar';  // Pongo el texto que necesito en un TextArea
   ovElemento.item(5).click;                             // Hago el Submit

end;

Hasta aquí funciona correctamente. Pero cuando quiero hacerlo todo seguido, por ejemplo al pulsar también un TButtom, no me sale.
Código Delphi [-]
procedure TForm1.Button4Click(Sender: TObject);
Var
   ovElemento: OleVariant;
begin
// Cargo la página en cuestión
   WebBrowser1.Navigate(''direccion pagina web'');

// Espero a que esté totalmente cargada
   while webBrowser1.ReadyState < READYSTATE_INTERACTIVE do  Application.ProcessMessages;

// Doy valores a los elementos CONOCIDOS que me interesan
   ovElemento := WebBrowser1.OleObject.Document.forms.item(0).elements;

   ovElemento.item(1).value:='usuario';        // Escribe en la página el usuario
   ovElemento.item(2).value:='contraseña';  // Escribe en la página la password
   ovElemento.item(3).click;                      // Mandamos al servidor la información

   ovElemento:= WebBrowser1.OleObject.Document.links;
   ovElemento.item(38).click;  // ********** AQUI FALLA ***************

   ovElemento := WebBrowser1.OleObject.Document.forms.item(1).elements;

   ovElemento.item(2).value := 'Texto a enviar'';  // Pongo el texto que necesito en un TextArea
   ovElemento.item(5).click;                             // Hago el Submit

end;
Seguramente será una tontería, o incluso de la página en cuestión, pero llevo dándole vueltas varios días y no consigo dar con la solución.

He comprobado que si antes del fallo interrumpo el programa, por ejemplo con un showmessage() , si me funciona. ¿¿??, pero con un sleep() no.

Gracias anticipadas.

Jovalca 12-03-2015 07:33:31

Hola Jontart.

Cuando haces esto, el webbrowser dirige a otra página?

Cita:

Empezado por Jontart (Mensaje 489901)
Código Delphi [-]
   
   ovElemento.item(1).value:='usuario';        // Escribe en la página el usuario
   ovElemento.item(2).value:='contraseña';  // Escribe en la página la password
   ovElemento.item(3).click;                      // Mandamos al servidor la información

Saludos.

Jontart 12-03-2015 08:00:05

Si.
Es la típica entrada de usuario. Realmente, una vez pasada entra en la aplicación, aunque con la misma raiz.

Jontart 12-03-2015 08:05:14

Para solventar el problema, y no entiendo bien porqué, lo que he hecho ha sido, puesto que observé que al hacer un showmessage() no se producía el error, crear un nuevo form "temporal", en el punto dónde dejaba de correr el programa; este nuevo form, abierto como showModal, se cierra el solito una vez pasados 3 segundos y la aplicación contínua tan ricamente.

NO sé porqué, pero me está funcionado. Me gustaría encontrar la forma elegante de hacerlo y el motivo por el que no funciona.

Saludos.

Jovalca 12-03-2015 08:10:59

Ok, se me ocurre así de pronto que quizá cuando lo haces con los botones, el tiempo que transcurre desde que hace login hasta que pulsas el siguiente botón, es suficiente para que la página donde se encuentra el link cargue completamente.

Pero cuando lo haces todo seguido no le das tiempo suficiente para que cargue con lo que creo le es imposible encontrar el item(38).

Has probado a esperar a que la página cargue después del login?

No lo he probado... Pero intenta poner la linea de espera también aqui o retrasar la segunda accion.

Código Delphi [-]
procedure TForm1.Button4Click(Sender: TObject);
Var
   ovElemento: OleVariant;
begin
// Cargo la página en cuestión
   WebBrowser1.Navigate(''direccion pagina web'');

// Espero a que esté totalmente cargada
   while webBrowser1.ReadyState < READYSTATE_INTERACTIVE do  Application.ProcessMessages;

// Doy valores a los elementos CONOCIDOS que me interesan
   ovElemento := WebBrowser1.OleObject.Document.forms.item(0).elements;

   ovElemento.item(1).value:='usuario';        // Escribe en la página el usuario
   ovElemento.item(2).value:='contraseña';  // Escribe en la página la password
   ovElemento.item(3).click;                      // Mandamos al servidor la información

   while webBrowser1.ReadyState < READYSTATE_INTERACTIVE do  Application.ProcessMessages;

   ovElemento:= WebBrowser1.OleObject.Document.links;
   ovElemento.item(38).click;  // ********** AQUI FALLA ***************

   ovElemento := WebBrowser1.OleObject.Document.forms.item(1).elements;

   ovElemento.item(2).value := 'Texto a enviar'';  // Pongo el texto que necesito en un TextArea
   ovElemento.item(5).click;                             // Hago el Submit

end;

Ya me diras si era eso.
Saludos.

fjcg02 12-03-2015 08:48:11

Como dice Jovalca, cuando lo haces todo seguido no dejas que las respuestas a lo que solicitas lleguen.

Al hacerlo con botones o poniendo mensajes en medio, dejas suficiente tiempo para que la respuesta a las acciones que haces llegue.

Esa es la respuesta a tu pregunta.

Si pones una espera de por ejemplo 2 segundos entre acción y acción, seguro que funciona.

Un saludo

Jontart 14-03-2015 11:10:56

Perdón por la tardanza, en contestar.

Eso es lo que, en principio, suponía que pasaba, que la página no estaba totalmente cargada. Pero, por ejemplo, no funciona si hago un sleep() de 10 segundos, o un ciclo For muy largo. Sólo funciona si, de alguna manera, salgo del procedimiento que está corriendo, aunque sea por un breve periodo de tiempo (1 segundo, p.e.). Por eso SI que funciona si lo ejecuto desde otro botón, si hago correr un nuevo form durante un tiempo determinado, o si ejecuto un ShowMessage, que es modal.

El programa, ahora, se ejecuta bien; lo que quería saber es porqué. Qué órdenes debo usar para parar totalmente un procedimiento, en el entorno web, hasta obtener la respuesta deseada y que funcione elegantemente.
Código:

while webBrowser2.ReadyState < READYSTATE_INTERACTIVE do
  Application.ProcessMessages;

¡Ésta no funciona adecuadamente!

Gracias.

Jovalca 14-03-2015 11:57:27

Hola otra vez Jontart.

Hace tiempo que migré a Lazarus y a Mac pero creo recordar que TWebBrowser dispone de un evento OnNavigateComplete o TWebBrowser.OnNavigateComplete2 que puede servirte para lo que necesitas. Inserta las acciones despues del login en ese evento a ver si se soluciona.

Saludos.

Jontart 14-03-2015 13:48:05

Si que FUNCIONA.

Utilizando los eventos OnBeforeNavigate(), OnDocumentComplete() y OnNavigateComplete2() se consigue lo que quería sin artificios extraños.

Defino dos variables y creo los eventos:
Código Delphi [-]
var
  Form1: Tform1;
  CurDispatch: IDispatch;
  FDocLoaded: Boolean;

implementation

{$R *.dfm}

procedure TACDM.WebBrowser1BeforeNavigate2(Sender: TObject;
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
begin
    CurDispatch := nil;
    FDocLoaded := False;
end;

procedure TACDM.WebBrowser1NavigateComplete2(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
   if CurDispatch = nil then
        CurDispatch := pDisp;
end;

procedure TACDM.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
   if (pDisp = CurDispatch) then  
      begin
        FDocLoaded := True;
        CurDispatch := nil;
      end;
end;
Ahora, en el programa, después de cada acción que requiera una respuesta del servidor pongo:
Código Delphi [-]
   repeat Application.ProcessMessages until FDocLoaded;
y eso es todo.

Gracias por vuestra inestimable ayuda.


La franja horaria es GMT +2. Ahora son las 01:18:26.

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