[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1804
  • Last Modified:

Checking if a value exists in a form (TWebBrowser)

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
E-T
Asked:
E-T
  • 7
  • 5
1 Solution
 
fsurferCommented:
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
 
E-TAuthor Commented:
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
 
fsurferCommented:
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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
E-TAuthor Commented:
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
 
fsurferCommented:
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
 
E-TAuthor Commented:
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
 
fsurferCommented:
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
 
E-TAuthor Commented:
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
 
E-TAuthor Commented:
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
 
E-TAuthor Commented:
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
 
fsurferCommented:
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
 
E-TAuthor Commented:
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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 7
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now