Solved

TWebBrowser -- how?

Posted on 2002-06-29
26
1,944 Views
Last Modified: 2012-06-27
Hi All,
I have a TWebBrowser component on my form, I pass a url to the component and everything is cool.

The url contains a form which I want to fill out. Javascript gives me a permission denied error. Is there a way to reference form fields in the web browser as objects and set the values to what I want?

Up to 500pts available.
-max
0
Comment
Question by:maxb
  • 12
  • 12
  • +1
26 Comments
 
LVL 7

Expert Comment

by:Motaz
Comment Utility
You can use Indy HTTP client idHTTP to post data to a web server.

Motaz
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
maxb,

1. Do you want to general principle of filling form fields for any url, or just this one?

2. When you navigate to this url using IE, can you fill the form OK (by hand) ?

3. What version of Delphi do you have?
0
 

Author Comment

by:maxb
Comment Utility
Pretend I wanted to automate the posting of questions or something to EE. I know I can pass the parameters to their script in the URL but some people check the referring URL and know that they are being tricked.

I am doing this to automate my submission process. I submit my artwork to 12 sites 3 times a day and its tedious.

Yes you can fill the form out by hand. Its just a website on as server I DO NOT own. If i try to use javascript, it gives me a "Permission Denied" because it thinks its malicious or something.

Again, I need to fill out the form on someone elses server, I can click the submit button manually, I cant be downloading the form, filling out and then clicking submit.

I have delphi 3-6 so any is fine :)
Thanks again.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
maxb,

Following code requires you to check html source
of the form you want to submit.
I posted 2 demos for expert-exchange form.Place WebBrowser1 and 2 Buttons on the form for demos.

Copy/Paste:
--------------------

procedure TForm1.PostToURL(URL, Data: String);
//Post data string to the specified URL
var  a,b,c,d: OLEVariant;
     DataSize, Count: Integer;
begin
  if (URL = '') then exit;
  //Set the flags:
  a:=14;
  //Get the length of the post string:
  DataSize:= Length(Data);
  //Create a Variant array of bytes:
  c:= VarArrayCreate([0, DataSize], varByte);
  //Loop through each character and set the array element to the corresponding character:
  for Count:= 0 to DataSize - 1 do c[Count]:= Ord(Data[Count+1]);
  //Add the null terminating character:
  c[DataSize]:= 0;
  //Type cast it to variant array
  TVarData(c).vtype:= varArray;
  //Set the encoding header:
  d:= 'Content-Type: application/x-www-form-urlencoded'+#13+#10+#0;
  //Keep current frame:
  b:= '_top';
  // Finally post data:
  WebBrowser1.Navigate(URL, a, b, c, d);
end;


Demo 1:
------------

procedure TForm1.Button1Click(Sender: TObject);
begin
  // submits search to ex-ex for keyword 'internet':
  PostToURL('http://www.experts-exchange.com/jsp/qSearch.jsp', 'keyWord=internet');
end;


Demo 2:
------------

procedure TForm1.Button2Click(Sender: TObject);
begin
  // logs you on ex-ex (replace string XXXXX with your password):
  PostToURL('http://www.experts-exchange.com/jsp/memberLogin.jsp',
            'loginMemberName=maxb&loginPassword=XXXXX');
end;

0
 

Author Comment

by:maxb
Comment Utility
Thats what I meant by "I know I can pass the parameters to their script in the URL but some people check the referring URL and know that they are being tricked."

If they looked for the referring URL, they would see that the post to http://www.experts-exchange.com/jsp/qSearch.jsp came from nowhere and not http://www.experts-exchange.com for example.

Am I reading this wrong?
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
maxb,

> Am I reading this wrong?

No you are not.
Sorry, didn't get your point right away.


> Is there a way to reference form fields in the web browser as objects and set the values to what I want?

I think I saw this before. I'll try and post something for you later.  
Do you need only form auto-fill or auto-fill and auto-click on Submit button?
0
 

Author Comment

by:maxb
Comment Utility
I will click the submit button myself.
Thank you for your help.
0
 
LVL 7

Accepted Solution

by:
Cynna earned 250 total points
Comment Utility
maxb,

First thing you need is add MSHTML_TLB, COMOBJ to your uses clause.
If the compiler complains, you probably don't have MSHTML_TLB.pas. In that case, you should import Microsoft HTML Object Library (Project->Import Type Library).
During import, you'll have to wait quite a while (it generates over 10Mb source ), so don't loose your patiance, or think your machine has frozen :) ....

Finally just Copy/Paste following function:

function FillFormField(Browser:TWebBrowser; FieldName, FieldValue: String): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
     begin
        if InputElement.Get_type_ = 'text' then begin
           InputElement.Set_value(FieldValue);
           Result:=TRUE;
        end;
     end;
end;


DEMO:
-------
(place TWebBrowser and TButton on the form)


procedure TForm2.Button2Click(Sender: TObject);
begin
   WebBrowser1.Navigate('http://www.experts-exchange.com/');
   // Wait for page to fully load:
   while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do begin
         Sleep(1);
         Application.ProcessMessages;
   end;
   // Fill the search field (named keyWord) with some text:
   FillFormField(WebBrowser1, 'keyWord', '....My search here....');
end;
0
 

Author Comment

by:maxb
Comment Utility
Ok, I feel like an idiot. While playing around, I removed the Microsoft HTML Object Library. How do I readd it? :)

I tried reinstalling d4 but no luck.

Thanks guys so much.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
Oh well, I have no hands-on expiriance with this type of situation...
Probably redundant question, but did you try simply repeating Project->Import Type Library, and if yes, what happened exactly?
0
 

Author Comment

by:maxb
Comment Utility
I did, the Microsoft HTML Object Library wasnt on the list of items to import.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
Just curious, what did you do during this 'playing around'?  You didn't click 'Remove' button now, didn't you?

Anyway, if you didn't do something really bad to your system, this shoud get you back:
Project->Import Type Library-> Add (opposite from Remove :-)
Then surf to your windows system folder, and look for:
mshtml.tlb

Click OK, and that's it; you should now have your Microsoft HTML Object Library again.
Click 'Install' on it and take a cup of cofee...
After a while, you should have MSHTML_TLB.pas.
Now go back and Copy/Paste my example.
0
 

Author Comment

by:maxb
Comment Utility
Cool,
It worked but wouldnt compile. Has problems with the "fonts". Did yours compile? What version of Delphi are you using?

-max
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 7

Expert Comment

by:Cynna
Comment Utility
> Did yours compile? What version of Delphi are you using?

I'm using D5 Enterprise on WinXP, and it compiles without any problems.


> Has problems with the "fonts".

Well, that's not exactly what I'd call a "detailed bug report"... ;)

1. What error message you received exactly ? (copy/paste, please)

2. What line(s) cause this error? (copy/paste problematic line(s)and neighboring lines)
   
3. What OS do you have?


I'm a bit busy right now, so please be patient, I'll get to you later...

In the meanwhile, there are few things for you to try yourself:

1. You said you have D3-D5. Try this on D5 or D6.

2. If you're in a hacking mood, you might try just commenting out
   that line(s) in MSHTML_TLB.pas and see if it compiles OK.
   Probably won't work right away, but won't cost you much...
0
 

Author Comment

by:maxb
Comment Utility
It only works in d4 for me, I cant find my d5.
But, d4 doesnt have a TWebBrowser component.

[Error] MSHTML_TLB.pas(97982): Undeclared identifier: 'Get_fontFamily'
[Error] MSHTML_TLB.pas(97998): Undeclared identifier: 'Get_fontStyle'

and so on.

    procedure Set_textKashida(Param1: OleVariant);
    function  Get_textKashida: OleVariant;
    procedure Set_textAutospace(const Param1: WideString);
    function  Get_textAutospace: WideString;

line 32447, this is in D6. I am running XP.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
maxb,

> I cant find my d5.

Then it looks like we're in trouble. I can only speculate about possible solutions, because I can only access D5.


> It only works in d4 for me...
> But, d4 doesnt have a TWebBrowser component

Did you try this:
- Components->Import ActiveX Control,
- select "Microsoft Internet Controls"
- if you can't see it, I think this file is SHDOCVW.DLL; it should be in your system folder.


As for D6:

> Undeclared identifier: 'Get_fontFamily'.... in D6 ...

Well, D6 TLIBIMP.EXE (type library importer) seem to be buggy.
As far as I can see, you have two choices:

1) Update to newest D6 service pack. Also, it might be good  
   idea to search for newest (hopeffuly fixed) TLIBIMP.EXE
   for D6.
   
2) There is a "beta" & "unofficial" version of TLIBIMP.EXE
   that claims to solve some of the problems:
   
   http://www.pdmagic.com/download/tlibimp.zip

  If you decide to give it a try, make a backup of the
  existing one, of course.

0
 

Author Comment

by:maxb
Comment Utility
Cool, ill try it over the weekend.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
Well, did it work?
0
 

Author Comment

by:maxb
Comment Utility
Sorry, I was on a business trip. No, it still will not compile. Is there any way someone could compile it and give it to me or is there a way to do it with d4?

Thank you.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
What happens in D4?

> It only works in d4 for me...
> But, d4 doesnt have a TWebBrowser component

Do you mean you can import MSHTML_TLB.pas from D4, but
don't have TWebBrowser? What happened when you tried importing "Microsoft Internet Controls" as I suggested?


> Is there any way someone could compile it and give it to me
If none of the proposed ways for D6 didn't work out,
you need access to a machine with D5.
There, you should generate MSHTML_TLB.pas and copy it to
your Imports directory.
Unfortunately, MSHTML_TLB.pas is about 10Mb, which makes
it very hard for download from someone else, unless, of course, you have fixed net connection.
0
 

Author Comment

by:maxb
Comment Utility
Ok, sweet.

[Error] Unit1.pas(56): Not enough actual parameters

AT:

WebBrowser1.Navigate('http://www.experts-exchange.com/');

It wants 4 more OLEVariant type parameters. I have no idea what to put there.

Please advise.
0
 

Author Comment

by:maxb
Comment Utility
Got it to work. Ill post final code and grade of A with 250pts if you can tell me how to check and uncheck a checkbox, radio button, change selection in a dropdown

Thank you again so much.
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
So, what was the problem?

About your additional requests... well, I don't know this exactly offhand - will have to search MSDN a while. This is a bit of work, especially if you want working copy/paste demo. I'm kind of short on time right now, so please be patient...
0
 

Author Comment

by:maxb
Comment Utility
Thank you. The key was to read the MSHTML_TLB.pas
0
 
LVL 7

Expert Comment

by:Cynna
Comment Utility
Here you go:

function FillFormField(Browser:TWebBrowser; FieldName, FieldValue: String): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
     begin
        if InputElement.Get_type_ = 'text' then begin
           InputElement.Set_value(FieldValue);
           Result:=TRUE;
        end;
     end;
end;

function CheckFormField(Browser:TWebBrowser; FieldName: String; CheckBoxIndex: Integer; CheckIt: Boolean): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, CheckBoxIndex);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
        if InputElement.Get_type_ = 'checkbox' then  InputElement.checked:=CheckIt;
end;

function RadioFormField(Browser:TWebBrowser; FieldName: String; RadioIndex: Integer): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, RadioIndex);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
        if InputElement.Get_type_ = 'radio' then InputElement.checked:=TRUE;
end;

function SelectFormField(Browser:TWebBrowser; FieldName, SelectionIndex: String): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    SelectElement: IHTMLSelectElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLSelectElement, SelectElement) = 0 then
        SelectElement.selectedIndex:=StrToInt(SelectionIndex);
end;



// DEMO
// -------------
// (you'll need Button1 and Button2)

procedure TForm1.Button1Click(Sender: TObject);
var site: String;
begin
   site:='http://edit.yahoo.com/config/eval_register?.intl=us&new=1&.done=&.src=ym&.partner=&.p=&promo=&.last=';
   WebBrowser1.Navigate(site);
   // Wait for page to fully load:
   while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do begin
         Sleep(1);
         Application.ProcessMessages;
   end;
   // Fill first name:
   FillFormField(WebBrowser1, '.fn', 'maxb');
   // Uncheck  special offers.. field:
   CheckFormField(WebBrowser1, '.offer', 0, FALSE);
   // Check Entertainment and Computers & Technology fields
   CheckFormField(WebBrowser1, '.userPrefs', 0, TRUE);
   CheckFormField(WebBrowser1, '.userPrefs', 5, TRUE);
   // Select 5. element from Industry field (Computers):
   SelectFormField(WebBrowser1, '.ind' , '5');
end;

procedure TForm1.Button2Click(Sender: TObject);
var site: String; // Radio button demo
begin
   site:='http://www.altavista.com/sites/search/webadv';
   WebBrowser1.Navigate(site);
   // Wait for page to fully load:
   while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do begin
         Sleep(1);
         Application.ProcessMessages;
   end;
   // check 'only this host or URL'::
   RadioFormField(WebBrowser1, 'rc', 2);
   // check 'by date range':
   RadioFormField(WebBrowser1, 'dt', 1);
end;

0
 
LVL 2

Expert Comment

by:ozi_lion
Comment Utility
Hello, I know this is very old question but I need to use those codes with SSL enabled sites and frame enabled sites, I have tried to change the code but no chance,  can someone help me about it. Thanks in advance.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now