maxb
asked on
TWebBrowser -- how?
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
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
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?
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?
ASKER
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.
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.
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-url encoded'+# 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('https://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('https://www.experts-exchange.com/jsp/memberLogin.jsp',
'loginMemberName=maxb&logi nPassword= XXXXX');
end;
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-url
//Keep current frame:
b:= '_top';
// Finally post data:
WebBrowser1.Navigate(URL, a, b, c, d);
end;
Demo 1:
------------
procedure TForm1.Button1Click(Sender
begin
// submits search to ex-ex for keyword 'internet':
PostToURL('https://www.experts-exchange.com/jsp/qSearch.jsp', 'keyWord=internet');
end;
Demo 2:
------------
procedure TForm1.Button2Click(Sender
begin
// logs you on ex-ex (replace string XXXXX with your password):
PostToURL('https://www.experts-exchange.com/jsp/memberLogin.jsp',
'loginMemberName=maxb&logi
end;
ASKER
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 https://www.experts-exchange.com/jsp/qSearch.jsp came from nowhere and not https://www.experts-exchange.com for example.
Am I reading this wrong?
If they looked for the referring URL, they would see that the post to https://www.experts-exchange.com/jsp/qSearch.jsp came from nowhere and not https://www.experts-exchange.com for example.
Am I reading this wrong?
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?
> 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?
ASKER
I will click the submit button myself.
Thank you for your help.
Thank you for your help.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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.
I tried reinstalling d4 but no luck.
Thanks guys so much.
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?
Probably redundant question, but did you try simply repeating Project->Import Type Library, and if yes, what happened exactly?
ASKER
I did, the Microsoft HTML Object Library wasnt on the list of items to import.
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.
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.
ASKER
Cool,
It worked but wouldnt compile. Has problems with the "fonts". Did yours compile? What version of Delphi are you using?
-max
It worked but wouldnt compile. Has problems with the "fonts". Did yours compile? What version of Delphi are you using?
-max
> 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...
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...
ASKER
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.
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.
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.
> 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.
ASKER
Cool, ill try it over the weekend.
Well, did it work?
ASKER
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.
Thank you.
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.
> 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.
ASKER
Ok, sweet.
[Error] Unit1.pas(56): Not enough actual parameters
AT:
WebBrowser1.Navigate('https://www.experts-exchange.com/');
It wants 4 more OLEVariant type parameters. I have no idea what to put there.
Please advise.
[Error] Unit1.pas(56): Not enough actual parameters
AT:
WebBrowser1.Navigate('https://www.experts-exchange.com/');
It wants 4 more OLEVariant type parameters. I have no idea what to put there.
Please advise.
ASKER
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.
Thank you again so much.
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...
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...
ASKER
Thank you. The key was to read the MSHTML_TLB.pas
Here you go:
function FillFormField(Browser:TWeb Browser; FieldName, FieldValue: String): Boolean;
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
InputElement : IHTMLInputElement;
begin
Result:=FALSE;
OleCheck(Browser.Document. QueryInter face(IID_I HTMLDocume nt2, WebDoc));
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLFor mElement, FormElement));
pDispatch := FormElement.item(FieldName , 0);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLEle ment, FormItem));
if FormItem.QueryInterface(II D_IHTMLInp utElement, InputElement) = 0 then
begin
if InputElement.Get_type_ = 'text' then begin
InputElement.Set_value(Fie ldValue);
Result:=TRUE;
end;
end;
end;
function CheckFormField(Browser:TWe bBrowser; 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. QueryInter face(IID_I HTMLDocume nt2, WebDoc));
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLFor mElement, FormElement));
pDispatch := FormElement.item(FieldName , CheckBoxIndex);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLEle ment, FormItem));
if FormItem.QueryInterface(II D_IHTMLInp utElement, InputElement) = 0 then
if InputElement.Get_type_ = 'checkbox' then InputElement.checked:=Chec kIt;
end;
function RadioFormField(Browser:TWe bBrowser; FieldName: String; RadioIndex: Integer): Boolean;
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
InputElement : IHTMLInputElement;
begin
Result:=FALSE;
OleCheck(Browser.Document. QueryInter face(IID_I HTMLDocume nt2, WebDoc));
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLFor mElement, FormElement));
pDispatch := FormElement.item(FieldName , RadioIndex);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLEle ment, FormItem));
if FormItem.QueryInterface(II D_IHTMLInp utElement, InputElement) = 0 then
if InputElement.Get_type_ = 'radio' then InputElement.checked:=TRUE ;
end;
function SelectFormField(Browser:TW ebBrowser; FieldName, SelectionIndex: String): Boolean;
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
SelectElement: IHTMLSelectElement;
begin
Result:=FALSE;
OleCheck(Browser.Document. QueryInter face(IID_I HTMLDocume nt2, WebDoc));
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLFor mElement, FormElement));
pDispatch := FormElement.item(FieldName , 0);
OleCheck(pDispatch.QueryIn terface(II D_IHTMLEle ment, FormItem));
if FormItem.QueryInterface(II D_IHTMLSel ectElement , SelectElement) = 0 then
SelectElement.selectedInde x:=StrToIn t(Selectio nIndex);
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<>RE ADYSTATE_C OMPLETE do begin
Sleep(1);
Application.ProcessMessage s;
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(WebBrowser 1, '.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<>RE ADYSTATE_C OMPLETE do begin
Sleep(1);
Application.ProcessMessage s;
end;
// check 'only this host or URL'::
RadioFormField(WebBrowser1 , 'rc', 2);
// check 'by date range':
RadioFormField(WebBrowser1 , 'dt', 1);
end;
function FillFormField(Browser:TWeb
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
InputElement : IHTMLInputElement;
begin
Result:=FALSE;
OleCheck(Browser.Document.
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn
pDispatch := FormElement.item(FieldName
OleCheck(pDispatch.QueryIn
if FormItem.QueryInterface(II
begin
if InputElement.Get_type_ = 'text' then begin
InputElement.Set_value(Fie
Result:=TRUE;
end;
end;
end;
function CheckFormField(Browser:TWe
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
InputElement : IHTMLInputElement;
begin
Result:=FALSE;
OleCheck(Browser.Document.
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn
pDispatch := FormElement.item(FieldName
OleCheck(pDispatch.QueryIn
if FormItem.QueryInterface(II
if InputElement.Get_type_ = 'checkbox' then InputElement.checked:=Chec
end;
function RadioFormField(Browser:TWe
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
InputElement : IHTMLInputElement;
begin
Result:=FALSE;
OleCheck(Browser.Document.
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn
pDispatch := FormElement.item(FieldName
OleCheck(pDispatch.QueryIn
if FormItem.QueryInterface(II
if InputElement.Get_type_ = 'radio' then InputElement.checked:=TRUE
end;
function SelectFormField(Browser:TW
var WebDoc : IHTMLDocument2;
pDispatch : IDISPATCH;
FormCollection : IHTMLElementCollection;
FormElement : IHTMLFormElement;
FormItem : IHTMLElement;
SelectElement: IHTMLSelectElement;
begin
Result:=FALSE;
OleCheck(Browser.Document.
FormCollection := WebDoc.Get_forms;
pDispatch := FormCollection.item(0, 0);
OleCheck(pDispatch.QueryIn
pDispatch := FormElement.item(FieldName
OleCheck(pDispatch.QueryIn
if FormItem.QueryInterface(II
SelectElement.selectedInde
end;
// DEMO
// -------------
// (you'll need Button1 and Button2)
procedure TForm1.Button1Click(Sender
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<>RE
Sleep(1);
Application.ProcessMessage
end;
// Fill first name:
FillFormField(WebBrowser1,
// Uncheck special offers.. field:
CheckFormField(WebBrowser1
// Check Entertainment and Computers & Technology fields
CheckFormField(WebBrowser1
CheckFormField(WebBrowser1
// Select 5. element from Industry field (Computers):
SelectFormField(WebBrowser
end;
procedure TForm1.Button2Click(Sender
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<>RE
Sleep(1);
Application.ProcessMessage
end;
// check 'only this host or URL'::
RadioFormField(WebBrowser1
// check 'by date range':
RadioFormField(WebBrowser1
end;
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.
Motaz