Solved

Checking if a value exists in a form (TWebBrowser)

Posted on 2003-10-21
12
1,531 Views
Last Modified: 2010-05-18
Hi,

I'm having a little problem with checking if a value exists in an HTML form. I have a TWebBrowser control. It navigates to a website where the user performs a registration process. I need to pull a value from the form to see how far along the process the user has gone. Now, if there is any problem, and the form is not loaded, obviously that value will not be in the page. I use the following code to retrieve the value :

RegProcStr := WebBrowser.OleObject.Document.getElementByID('RegProc').value;

How do i check if the value exists before i retrieve it, if the value is not there, i get an error.

Thanks in advance.
0
Comment
Question by:E-T
  • 7
  • 5
12 Comments
 

Expert Comment

by:fsurfer
ID: 9591777
hi,

do you mean you have an error on this line or do you want to perform a check before the page loads ?

in the first case, you can use a
try
    RegProcStr := WebBrowser.OleObject.Document.getElementByID('RegProc').value;
except
    .. do whatever in case of an error
End;

in the second case, if you manage on your web server the registration process, add a value to the form (like test=1)
and, using a TidHTTP (Indy non visual component), load the URL to check if there's the wanted value in the reponse.
if the requested value is present, then load the url (with test=0) in the WebBrowser object.

HTH,

Guillaume
0
 

Author Comment

by:E-T
ID: 9595613
I'm checking on the document complete event, so the form has already been requested. However, this application is going to be mass marketed, so it is quite likely someone will try and run it without a net connection being present, if so, the value will not be in the form.

I would like to know if there is a way to check if the value is in the form before i retrieve it. I know that putting it into a try...execept will handle the error, but that means that every time i'm doing offline testing, delphi will interrupt the program when that exception happens. Which leads me to another question. How do i tell delphi not to interrupt program execution when an exception is found?

Surely there is a way to test for the presence of a value before retrieving it.

If i put the result of :
WebBrowser.OleObject.Document.getElementByID('RegProc') into a variant, it will either be an object, which has a useablel value parameter, or it will be something else which tells me that the requested item is not found. There are various different variant types, for instance varInteger, or varString. When i tested that variable. Whether or not the value was present, it told me that the varient type was varDispatch.

How do i determine what the result of that request was? Checking for nil is not allowed on variants, checking if it is 0 does nothing usefull.....
0
 

Expert Comment

by:fsurfer
ID: 9597348
hi,

WebBrowser.OleObject.Document.getElementByID('RegProc')  will return an objet of type IHTMLElement. You can check all this in {$DELPHI}/source/internet/MSHTML.PAS (which mean it is an interface object, which has properties and methods you can use)

BTW, you should let your application being able to be halted on severe exceptions. Else you could have your application in a hazardous state and it couldn't work properly after that.

the best, and easiest way, IMHO, is to code all your 'internet' access in a unit and manage the exceptions in it. as you know whenever you access the net, it'll be easier to manage.

the thing to know if you have a net access is ti write a function which will check (with a try ...except) if you can ping, or "http open" a page. if you have an error, your function can return a boolean which will tell if you can open the form (or check the value).

HTH,

Guillaume
0
 

Author Comment

by:E-T
ID: 9599156
Ok, well, checking the variant is rather difficult though, i still don't know how to do type checking on a variant that uses an external type, ie the IHTMLElement. The "is" operator is not allowed.

Anyway, i found the solution, it is as follows :

Found := False;
for Cnt := 0 to WebBrowser.OleObject.Document.All.Length - 1 do
begin
    if Pos('RegProc',WebBrowser.OleObject.Document.All.Item(Cnt).ID) <> 0 then
    begin
        Found := True;
    end;
end;
If (Found) Then ShowMessage('Found') else ShowMessage('Not Found');

You have been quite helpfull, and i'll give you the points if you can give me a few tips on how to check if an internet connection is present. I cannot use a ping because there is a problem with the hosting my client is using. Ping resolves the IP, but does not get a response. The website IS working though.

I found some other code which checks for a net connection using a windows API call, but it only seems to work if the computer is connected directly though a modem. If it is on a network, it says there is no connection.

So there's the initial problem if just seeing if a connection is available. Secondly, there is checking if the website itself is up using an HTTPGet of some kind. Could you post a bit of code showing how one uses the TidHTTP class?

If you can help me with both of these, i'll give you the initial 150, plus an extra 100 points.
0
 

Expert Comment

by:fsurfer
ID: 9599952
Hi,

In case of a computer on an LAN, i'm not sure about the way to know if an internet connection exists or not except by doing a ping (using TidICMPClient and getting the answer in the OnReply event). or a http reqest with a timeout.
The thing is that if you use a ping or http request, you may trigger a connection dialog if the computer uses a modem and is not constantly connected. For info, here's a sample code from the PingGUI Indy Demo :

(starring in alphabetical order : a form, an edit box - edtHost - an ICMP client and a ListBox - lstReplies)

procedure TfrmPing.btnPingClick(Sender: TObject);
var
  i: integer;
begin
  ICMP.OnReply := ICMPReply;
  ICMP.ReceiveTimeout := 1000;
  btnPing.Enabled := False;
  try
    ICMP.Host := edtHost.Text;
    for i := 1 to 4 do begin
      ICMP.Ping;
      Application.ProcessMessages;
    end;
  finally
     btnPing.Enabled := True;
  end;
end;

procedure TfrmPing.ICMPReply(ASender: TComponent; const ReplyStatus: TReplyStatus);
var
  sTime: string;
begin
  // TODO: check for error on ping reply (ReplyStatus.MsgType?)
  if (ReplyStatus.MsRoundTripTime = 0) then
    sTime := '<1'
  else
    sTime := '=';

  lstReplies.Items.Add(Format('%d bytes from %s: icmp_seq=%d ttl=%d time%s%d ms',
    [ReplyStatus.BytesReceived,
    ReplyStatus.FromIpAddress,
    ReplyStatus.SequenceId,
    ReplyStatus.TimeToLive,
    sTime,
    ReplyStatus.MsRoundTripTime]));
end;

concerning the use of TidHTTP, in one of my application, i'm doing a http request on a website to get some information. This request has a timeout. Basically, it's to know if there's a new version of my application, but doesn't prevent my app from running if no connection is available. here's part of the code :

          ...
          aHttp:=TidHTTP.Create(Nil);
          try
             s:=aHttp.Get(url);
          Except
             s:='';
          End;
          FreeAndNil(aHttp);
          if s<>'' then
          ...
         
By default, the http timeout of a TIdHTTP object is set to 1 second (cf ReadTimeOut property in the online help).
BTW, this is a non-visual component.

HTH,

Guillaume
0
 

Author Comment

by:E-T
ID: 9610848
OK, Consider problem one solved, i'll be using a ping. I'm having problems with that code you gave me for the TidHTTP object though.

I've entered various urls. For instance 'http://www.google.com' or 'www.google.com'.

When i do, i get one of two errors. The first (Connection timed out) i assume is to do with the TimeOut property , i've looked around in the help, but can't find where to set the timeout.

The second says the following :

"Project PingApp.exe raised exception class EIdSocketError with message 'Socket Error # 10061 Connection refused.'. Process stopped."

Any idea why this is happening? (I am on a network with a proxy server...)
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Accepted Solution

by:
fsurfer earned 200 total points
ID: 9612683
Hi,

(first of all, i'm using Indy v9 on Delphi7).

From the online help of TidHTTP component :
Indicates the milliseconds to wait for a readable connection.

property ReadTimeout: Integer;

Description

ReadTimeout is an Integer property that indicates the number of milliseconds that the connection should wait for the peer connection to become readable using the protocol stack.

---

the connection refused (which should not appear if you're using the try...except...end;) comes from the fact you're behind a proxy. one of the TidHTTP property (ProxyParams) is an object of TidProxyConnectionInfo type.

some of TidProxyConnectionInfo properties are :
 Authentication
 BasicAuthentication
 ProxyPassword
 ProxyPort
 ProxyServer
 ProxyUsername

You can easily recognize their use from their names ;)

if you want to get the lastest version of IndyComponents (v9) and the online help plus some demos, have a look there http://www.indyproject.org/download/Indy9.html.

if you have troubles with part of your code, don't hesitate, post it, i'll have a look !

HTH,

Guillaume
0
 

Author Comment

by:E-T
ID: 9621137
Ah, the wonderfull world of development.

This question has evolved quite a bit, i must say. ;)

I can use a ping to check if there is an internet connection.
The current problem is checking if the website is up.

I can do that in two ways. Unfortunately the methods mentioned here get pretty complicated.

First i'd need to know how to check if the user is on a proxy, or a normal connection.
Next, how do i detect the proxy settings.
Lastly i find out how to put that all together using the idHTTP object.

The other option is that i create another TWebBrowser object in the background and request a page from it. I then use the previously posted code to check for a value. If it finds one, that means the site is up. This option is a lot simpler, since it sorts out the connectivity problems for me, but it will use a fair amount of memory for a simple check, not exactly a prime example of good coding. ;)

Still, it doesn't matter too much. What i need to do is spawn a thread, retrieve one value from the website, and then free all the things i used to do that with, so they'll only be in existance for a few seconds...

What do you think? Option 1 is definately more efficient, but it is a lot harder to ensure that it works properly. Option 2 is more costly, but i'm fairly certain i can get it working perfectly....
0
 

Author Comment

by:E-T
ID: 9643941
Ok fsurfer, thanks for your help, I've resolved all the problems. Looks like I'll have this app's registration system up and running by the end of the week. :)

As for the points issue, i've added an extra 50. Since you couldn't help with the second part of the problem, i'm using the solution mentioned in my previous post. It works perfectly, so no worries.

If you read this, i'd like to know one little thing. What version of Indy do you get with Delphi 6? I've looked all over and can't find any mention of the version.
0
 

Author Comment

by:E-T
ID: 9644339
By the way, for anyone else reading this question, the code I posted earlier (Which checks if a value exists on the form) was a bit incorrect, the Pos is unneccesary. This is the final version of it:

For Cnt := 0 to FWeb.OleObject.Document.All.Length - 1 do Begin
    If (FWeb.OleObject.Document.All.Item(Cnt).ID = 'StatusVal') Then
        Begin
           UValExists := True;
           UVal := FWeb.OleObject.Document.GetElementById('StatusVal').value;
        end;
End;
0
 

Expert Comment

by:fsurfer
ID: 9644375
Hi E-T,

sorry if i haven't answered your last post, but i wasn't at my office.
for the proxy settings, i have no answer yet. I will have a look at the Wininet.pas API.

here are some specifications about getting proxy settings and the use of wininet api :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wininet/wininet/handling_authentication.asp

Your solution (for the proxy) isn't a masterpiece in programming matters, but... it works ;)  (i use the same sometimes ;)

for the Indy version, look for the Indy's source code directory. there should be a 'IdVers.inc' file. In it, you have the current version you're using.

thanks for the accepted answer :)

HTH,

Guillaume
0
 

Author Comment

by:E-T
ID: 9645242
Sure, no problem. You've been rather helpfull. ;)

There is no IdVers.inc file in the Indy directory by the way. I guess it doesn't matter too much, I'll just update to the latest one and be done with it.

I'm hoping it'll fix another little annoyance I'm having with TidHTTPServer. I have it set up serving fairly large html documents, you nagivate them using a treeview. When you click too fast, an exception is raised, saying either "Connection closed gracefully", or some socket error. It is meant to be using multiple threads to serve content, and it can't have more than about 10 running no matter how fast I click, still, it stuffs up.

It doesn't kill the app or anything, but it does cause the internet connection dialog to pop up (if enabled), which is pretty damn annoying, especially since it is meant to run offline most of the time.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
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…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

762 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

19 Experts available now in Live!

Get 1:1 Help Now