【问题标题】:Delphi WebBrowsing德尔福网页浏览
【发布时间】:2020-04-11 17:43:45
【问题描述】:

我想自动化以下过程: 我登录一个网站。 在搜索页面,输入我要搜索的信息,点击搜索按钮。 点击加载我的结果。 从结果页面中,我选择预览 pdf 文件的选项,然后单击按钮。 此点击上传我的 pdf 文件。

如果我将这些命令拆分为按钮,然后一个接一个地按下它,一切正常,但是当我想连续执行所有命令时,我得到一个错误。 (我认为错误是因为 WebBrowser 没有加载所有内容。)请帮忙。

procedure TMainForm.Button10Click(Sender: TObject);
var doc :IHTMLDocument2;
    FileStream: TFileStream;
    StreamAdapter: IStream;
    PersistStreamInit: IPersistStreamInit;
    i, a, b : integer;
    sir: string;
    MergiInainte:boolean;'

begin
    MergiInainte:=false;
    WebBrowser1.Navigate('https://website/externallogin.aspx');'

    repeat
      if ((WebBrowser1.ReadyState = READYSTATE_COMPLETE) and (WebBrowser1.Busy = false)) then
        MergiInainte:=true;
    until MergiInainte;'   // This repeat is not working. Dont know why?

    //After webBrowser is fully loaded, the next code has to be run
    doc := WebBrowser1.Document AS IHTMLDocument2;
    WebFormSetFieldValue(doc,0,'txtNume','user');
    WebFormSetFieldValue(doc,0,'txtPwd','psswd');
    WebBrowser1.OleObject.Document.GetElementByID('tibAutentification').click;'

    //after the above code is fully executat, next code is in line
    WebBrowser1.Navigate('https://website/Pages/SearchTitle.aspx');

    //after the above code is executed, next i need to complete form element with what the nexd data
    doc := WebBrowser1.Document AS IHTMLDocument2;
    WebBrowser1.OleObject.Document.GetElementByID('chkTitleNo').click;
    WebFormSetFieldValue(doc,0,'txtTitleNo','28972');   //nr titlu de proprietate
    WebBrowser1.OleObject.Document.GetElementByID('tibSearch').click;

    WebBrowser1.OleObject.Document.GetElementByID('fdgMain:_ctl3:imbView').click;

    WebBrowser1.OleObject.Document.GetElementByID('tibViewPDF').click;  
end;


// But i'm getting error:  Access violation....read of adress 0000000.'

procedure TForm1.WebFormSetFieldValue(const document: IHTMLDocument2; const formNumber: integer; const fieldName, newValue: string) ;
var form : IHTMLFormElement;
    field: IHTMLElement;
begin
  form := WebFormGet(formNumber, WebBrowser1.Document AS IHTMLDocument2) ;
  field := form.Item(fieldName,'') as IHTMLElement;
  if field = nil then Exit;
  if field.tagName = 'INPUT' then (field as IHTMLInputElement).value := newValue;
  if field.tagName = 'SELECT' then (field as IHTMLSelectElement).value := newValue;
  if field.tagName = 'TEXTAREA' then (field as IHTMLTextAreaElement).value := newValue;
end;

【问题讨论】:

  • 我们读者看不到您的屏幕。您在哪 exact 行获取 AV?请将此信息添加到您的 q。
  • 看看this(虽然我不确定他为什么要处理3个事件而不仅仅是DocumentComplete)。

标签: delphi twebbrowser


【解决方案1】:

提交网络表单是一种导航,因此您必须在调用tibAutentification.click 后再次等待ReadyStateBusy 属性(假设这是网络表单的提交按钮)。与第二个Navigate() 通话相同。此外,您需要在等待浏览器准备好时抽取调用线程的消息队列,以便它可以正确处理其状态更改。

procedure TMainForm.Button10Click(Sender: TObject);
var
  doc: IHTMLDocument2;
  doc3: IHTMLDocument3;
  FileStream: TFileStream;
  StreamAdapter: IStream;
  PersistStreamInit: IPersistStreamInit;
  i, a, b : integer;
  sir: string;

  procedure WaitForReady;
  begin
    while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do
      Application.ProcessMessages;
  end;

begin
  WebBrowser1.Navigate('https://website/externallogin.aspx');

  WaitForReady;
  doc := WebBrowser1.Document as IHTMLDocument2;
  doc3 := doc as IHTMLDocument3;
  WebFormSetFieldValue(doc,0,'txtNume','user');
  WebFormSetFieldValue(doc,0,'txtPwd','psswd');
  doc3.GetElementByID('tibAutentification').click;

  WaitForReady;
  WebBrowser1.Navigate('https://website/Pages/SearchTitle.aspx');

  WaitForReady;
  doc := WebBrowser1.Document as IHTMLDocument2;
  doc3 := doc as IHTMLDocument3;
  doc3.GetElementByID('chkTitleNo').click;
  WebFormSetFieldValue(doc,0,'txtTitleNo','28972');   //nr titlu de proprietate
  doc3.GetElementByID('tibSearch').click;

  WaitForReady; // ?
  doc := WebBrowser1.Document as IHTMLDocument2;
  doc3 := doc as IHTMLDocument3;
  doc3.GetElementByID('fdgMain:_ctl3:imbView').click;

  WaitForReady; // ?
  doc := WebBrowser1.Document as IHTMLDocument2;
  doc3 := doc as IHTMLDocument3;
  doc3.GetElementByID('tibViewPDF').click;  
end;

procedure TForm1.WebFormSetFieldValue(const document: IHTMLDocument2;
  const formNumber: integer; const fieldName, newValue: string);
var
  form : IHTMLFormElement;
  field: IHTMLElement;
begin
  if document = nil then Exit;
  form := WebFormGet(formNumber, document);
  if form = nil then Exit;
  field := form.Item(fieldName,'') as IHTMLElement;
  if field = nil then Exit;
  if field.tagName = 'INPUT' then
    (field as IHTMLInputElement).value := newValue
  else if field.tagName = 'SELECT' then
    (field as IHTMLSelectElement).value := newValue
  else if field.tagName = 'TEXTAREA' then
    (field as IHTMLTextAreaElement).value := newValue;
end;

由于手动抽消息队列相关的重入问题,序列化这段代码不是一个好主意,你应该改用浏览器的OnDocumentComplete事件,让VCL为你处理消息,例如(可能需要一些调整):

procedure TMainForm.Button10Click(Sender: TObject);
begin
  WebBrowser1.Navigate('https://website/externallogin.aspx');
  WebBrowser1.Tag := 1;
end;

procedure TMainForm.WebBrowser1DocumentComplete(ASender: TObject;
  const Disp: IDispatch; const URL: OleVariant);
var
  doc: IHTMLDocument2;
  doc3: IHTMLDocument3;
begin
  case WebBrowser1.Tag of
    1: begin
      doc := WebBrowser1.Document as IHTMLDocument2;
      doc3 := doc as IHTMLDocument3;
      WebFormSetFieldValue(doc,0,'txtNume','user');
      WebFormSetFieldValue(doc,0,'txtPwd','psswd');
      doc3.GetElementByID('tibAutentification').click;
      WebBrowser1.Tag := 2;
    end;

    2: begin
      WebBrowser1.Navigate('https://website/Pages/SearchTitle.aspx');
      WebBrowser1.Tag := 3;
    end;

    3: begin
      doc := WebBrowser1.Document as IHTMLDocument2;
      doc3 := doc as IHTMLDocument3;
      doc3.GetElementByID('chkTitleNo').click;
      WebFormSetFieldValue(doc,0,'txtTitleNo','28972');   //nr titlu de proprietate
      doc3.GetElementByID('tibSearch').click;
      WebBrowser1.Tag := 4;
    end;

    4: begin
      doc := WebBrowser1.Document as IHTMLDocument2;
      doc3 := doc as IHTMLDocument3;
      doc3.GetElementByID('fdgMain:_ctl3:imbView').click;
      WebBrowser1.Tag := 5;
    end;

    5: begin
      doc := WebBrowser1.Document as IHTMLDocument2;
      doc3 := doc as IHTMLDocument3;
      doc3.GetElementByID('tibViewPDF').click;
      WebBrowser1.Tag := 0;
    end;
  end;
end;

【讨论】:

  • Indeed OnDocumentComplete,是正确的选择,不过要注意,如果网页有框架(每框架一次),它会被触发多次。
  • @whosrdaddy 很容易区分,使用Disp参数查看完成的文档是属于框架文档还是顶层文档。
  • 雷米,知道,做这些事情很长时间,只是想警告未来的读者这个罪魁祸首:)
  • 等待就绪; --> 不工作。 OnDocumentComplete --> 工作正常。谢谢你。有时 WebBrowser 会显示一个带有 ok 按钮的 MessageBox,知道如何自动捕获/关闭它。
猜你喜欢
  • 2014-07-08
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-03
  • 2011-07-02
相关资源
最近更新 更多