Link to home
Start Free TrialLog in
Avatar of kyrlean
kyrlean

asked on

How to open multiples browser's window (For a specific procedure..)

Hi, i've tried many things to get it done though, i couldn't get it yet. I got no erros but i got no lucky as well ! I'm using this procedure to autologin in webpages( emails and etc ) .What needs to be done to open more than one browser's instance, allowing me to login to different pages at once ?
Here it is...

procedure checkemail;
var
  hIE: HWND;
  handle: thandle;
  ShellWindow: IShellWindows;
  WB: IWebbrowser2;
  spDisp: IDispatch;
  IDoc1: IHTMLDocument2;
  Document: Variant;
  k, m: Integer;
  ovElements: OleVariant;
  i: Integer;
begin
ShellExecute(HANDLE,'open',PChar(url),nil,nil,SW_SHOW);

ShellWindow := CoShellWindows.Create;
 
  for k := 0 to ShellWindow.Count do
  begin
    spDisp := ShellWindow.Item(k);
    if spDisp = nil then Continue;
   
    spDisp.QueryInterface(iWebBrowser2, WB);

    if WB <> nil then
    begin
      WB.Document.QueryInterface(IHTMLDocument2, iDoc1);
      if iDoc1 <> nil then
      begin
        WB := ShellWindow.Item(k) as IWebbrowser2;
        begin
          Document := WB.Document;

         
          for m := 0 to Document.forms.Length - 1 do
          begin
            ovElements := Document.forms.Item(m).elements;
           
            for i := 0 to ovElements.Length - 1 do
            begin
             
              try
                if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'text') = 0) then
                begin
                  ovElements.item(i).Value := (usern);
                end;
              except
              end;
             
              try
                if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'password') = 0) then
                begin
                  ovElements.item(i).Value := (pass);
               // and so on.....

Thank you !
Avatar of sas13
sas13
Flag of Russian Federation image

ShellExecute(HANDLE,'open','explorer', PChar(url),nil,SW_SHOW);
I do something like this to open an url in a new window of the default browser

ShellExecute(HANDLE,'open',PChar(url), PChar(url+' -new'),nil,SW_SHOWNORMAL);
Avatar of kyrlean
kyrlean

ASKER

Well, if i'm not on mistake i already tried that, i'll check when i get home people.
Thanks a lot
Avatar of kyrlean

ASKER

As expected none of them worked in this case, in fact i already tried that before sas13, and it does fine but not for this example.
It really has something to do with the procedure itself though, i can figure that out. Any other idieas ?
Thanks !
my example works. I tested it before posting :P (delphi 7 by the way).

on first look, here are some issue:
 for k := 0 to ShellWindow.Count do should be  for k := 0 to ShellWindow.Count-1 do

is this delphi .net what you are using? if so, I'm out of this since I never seen that version yet :D

also, note that for shellexecute to work correctly, there must be a certain timelimit before consecutive calls. I tested 2 seconds and it worked fine. it might work for less, but I didn't test. I'm saying this in case you call that checkemail very often.

good luck
Avatar of kyrlean

ASKER

No, no i'm using D7. Well, if a delay is necessary let me give it a shot !
Avatar of kyrlean

ASKER

I'm getting crazy because of this.That's why i'm posting before  pay attention to.. what i did and what i didn't. I have different buttons for different sites, which means.. for now i'm not trying to open all of them at once, i'm trying one by one after they get loaded/completed. I can't even try it with Firefox because this code will only works with IE since it's written to interact with it.
If there is any work around ,( maybe a different procedure)  please feel free to post, points will get up to the ceiling :-)
in that case you need to adapt sas13's solution to call iexplore and not explorer

ShellExecute(HANDLE,'open','iexplore', PChar(url),nil,SW_SHOW);

tested. works (opens a new instance of IE for each execution).
Avatar of kyrlean

ASKER

Yeah, i did that already , i just tested yours in another PC to see if it works though, nothing ! Did you tested it with the procedure checkemail ? Because this is the problem i think, as i mentioned before, if the ideia was simply open multiples pages without such procedure i would be fine, let me test it a little more.
Maybe i could launch te browser and then call the procedure, leaving the shellexecute part out of it, anyway.. i believe i that too.
I'll get back to you !
Thanks !
I can't test with  checkemail procedure since it si not full.

how about you post the hole procedure for us to check that? ;)

also:

try doing this

ShellExecute(HANDLE,'open',PChar(url),nil,nil,SW_SHOW);
sleep(2000); <------------------------------------------------------------ ADD THIS LINE
ShellWindow := CoShellWindows.Create;

does the page load now?
Avatar of kyrlean

ASKER

I already have that sleep(3000); since i need sometime to allow the browser to acces the internet (firewall stuff :-) .before the procedure goes on.
About the procedure: i made some changes to the original one since i was having some problem with it,as well its name. What i have right after the line
ovElements.item(i).Value := (pass); // the last one above  is...
keybd_event(VK_RETURN,0,0,0);// another "compare text was used here to find and //click on the Submit button but,that was also not working properly.
end
except
end;
end;
end;
end;
end;
end;
end;
end;

Every button loads a different value for (url,usern,pass) as you  obviously noticed.It all works fine but,redirecting the  same window.
Hope it's clear .
Thanks again !
the following works fine for me (increase sleep value if slow connection):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses SHDocVw, MSHTML, shellapi;

procedure checkemail(handle:hwnd; url,usern,pass:string);
var
//  hIE: HWND;
//  handle: thandle;
  ShellWindow: IShellWindows;
  WB: IWebbrowser2;
  spDisp: IDispatch;
  IDoc1: IHTMLDocument2;
  Document: Variant;
  k, m: Integer;
  ovElements: OleVariant;
  i: Integer;
begin
ShellExecute(HANDLE,'open','iexplore',PChar(url),nil,SW_SHOW);
sleep(4000);
ShellWindow := CoShellWindows.Create;

  for k := 0 to ShellWindow.Count do
  begin
    spDisp := ShellWindow.Item(k);
    if spDisp = nil then Continue;
   
    spDisp.QueryInterface(iWebBrowser2, WB);

    if WB <> nil then
    begin
      WB.Document.QueryInterface(IHTMLDocument2, iDoc1);
      if iDoc1 <> nil then
      begin
        WB := ShellWindow.Item(k) as IWebbrowser2;
        begin
          Document := WB.Document;

         
          for m := 0 to Document.forms.Length - 1 do
          begin
            ovElements := Document.forms.Item(m).elements;
           
            for i := 0 to ovElements.Length - 1 do
            begin
             
              try
                if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'text') = 0) then
                begin
                  ovElements.item(i).Value := (usern);
                end;
              except
              end;
             
              try
                if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'password') = 0) then
                begin
                  ovElements.item(i).Value := (pass);
               // and so on.....
keybd_event(VK_RETURN,0,0,0);// another "compare text was used here to find and //click on the Submit button but,that was also not working properly.
end
except
end;
end;
end;
end;
end;
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  checkemail(handle, edit3.Text, edit1.text, edit2.text);
end;

end.

One thing to keep in mind:
keybd_event() works for the wondow/control that has focus. That means you cannot debug this part because the editor will have focus. just run the application and it will log in. If you want debugging, then consider saving to a file or putting it in a memo or something.
Avatar of kyrlean

ASKER

Right, i know about the keyboard thing.Well, i'll try it as soon as i get a chance,my (url,usern,pass) are hard coded strings, hopefully nothing goes wrong when replacing the edits for them !!
Thanks man !
Avatar of kyrlean

ASKER

Ciuly my friend ! I'll give up !
Your example gave me  the same result like the one i got just modifying the shellexecute. This is what happens :
I click on the button and it launches the browser but, the fields don't get filled.And then.. i click on the button again, it does all the process one more time ( opening a new instance) and the fields from the first opened window get filled, and the second one is still empty. Is Freud around or you can give me an explanation for that ?? Anyway let me try a little more and i'll give you the points, you deserve it, even though, the problem may reside on my pc, i don't know!
what you could try is increasing the sleep(4000); to say sleep(10000); or even sleep(15000);

why? because the page has to be completly (!) loaded before(!) ShellWindow := CoShellWindows.Create; is executed. I teste dthe code on a P4 with 1GB ram and I needed almost 4 seconds to be sure that the page is loaded. I think that might be the issue.

so my suggestion for now is
- to increase the sleep until the page is (absolutely) completly loaded (meaning nothing will be loaded afterwards: images/movies/etc)
- use my exact code in another, clean application (we have to take into consideration that your application might do something "bad" for this ;) )
- try using "http://mail.yahoo.com" as an url for testing (that's the one I used) You don't need to have an account: in case it works and you don't have an account you will just get an error that the account does not exist :)

don't forget: Delphi IDE: File -> New -> Application ;)
Avatar of kyrlean

ASKER

All right, things are getting better around here..Let me explain you shortly( i'll try it !! ).I found a parcial solution, i mean.. i 'm now able to open a new window and login to another account.It's working fine , if i open one by one.
The solution was another delay at the line below !
  if WB <> nil then
    begin

sleep(2000)        // RIGHT HERE ! ! !

      WB.Document.QueryInterface(IHTMLDocument2, iDoc1);
      if iDoc1 <> nil then
      begin
        WB := ShellWindow.Item(k) as IWebbrowser2;
        begin
          Document := WB.Document;
For otherwise i can't open several pages at once since i'm using that tricky " KEYBD_EVENT''. So i'm still not able to do what i really want though, i can work around this by myself.
Can you just try one last thing for me please ????
Replace the KEYBD_EVENT for the following code and see if it works for you, it doesn't for me !

 if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'SUBMIT') = 0) and
                  (ovElements.item(i).Value = 'Search') then
                begin
                  ovElements.item(i).Click;

Thanks !
well, I tried it with http://mail.yahoo.com (again :) ) and changed the "search" to "Sign In" and it works. here is the code:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses SHDocVw, MSHTML, shellapi;

procedure checkemail(handle:hwnd; url,usern,pass:string);
var
//  hIE: HWND;
//  handle: thandle;
  ShellWindow: IShellWindows;
  WB: IWebbrowser2;
  spDisp: IDispatch;
  IDoc1: IHTMLDocument2;
  Document: Variant;
  k, m: Integer;
  ovElements: OleVariant;
  i: Integer;
begin
ShellExecute(HANDLE,'open','iexplore',PChar(url),nil,SW_SHOW);
sleep(4000);
ShellWindow := CoShellWindows.Create;

  for k := 0 to ShellWindow.Count do
  begin
    spDisp := ShellWindow.Item(k);
    if spDisp = nil then Continue;

    spDisp.QueryInterface(iWebBrowser2, WB);

    if WB <> nil then
    begin
      WB.Document.QueryInterface(IHTMLDocument2, iDoc1);
      if iDoc1 <> nil then
      begin
        WB := ShellWindow.Item(k) as IWebbrowser2;
        begin
          Document := WB.Document;


          for m := 0 to Document.forms.Length - 1 do
          begin
            ovElements := Document.forms.Item(m).elements;

            for i := 0 to ovElements.Length - 1 do
            begin

              try
                if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'text') = 0) then
                begin
                  ovElements.item(i).Value := (usern);
                end;
              except
              end;
             
              try
                if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'password') = 0) then
                begin
                  ovElements.item(i).Value := (pass);
end
except
end;
//keybd_event(VK_RETURN,0,0,0);// another "compare text was used here to find and //click on the Submit button but,that was also not working properly.
try
 if (CompareText(ovElements.item(i).tagName, 'INPUT') = 0) and
                  (CompareText(ovElements.item(i).type, 'SUBMIT') = 0) and
                  (ovElements.item(i).Value = 'Sign In') then
                begin
                  ovElements.item(i).Click;
                end;  
except
end;
end;
end;
end;
end;
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  checkemail(handle, edit3.Text, edit1.text, edit2.text);
end;

end.

For testing I have commented out the shellexecute.

By the way, I use this code to "execute" an url:

procedure BrowseTo(sURL :String; handle:integer);
var sei: TShellExecuteInfo;
begin
   ZeroMemory(@sei, sizeof(sei));
   with sei do
   begin
     cbSize := SizeOf(sei);
     fMask  := SEE_MASK_NOCLOSEPROCESS;
     Wnd   := handle;
     lpVerb := 'open';
     lpFile := PChar(sURL);
     lpParameters := PChar(sURL + ' -new');
     lpDirectory := #0;
     nShow := SW_SHOWNORMAL;
   end;
   ShellExecuteEX(@sei);
end;

you will have to change this, because this launches default browser, to

procedure BrowseTo(sURL :String; handle:integer);
var sei: TShellExecuteInfo;
begin
   ZeroMemory(@sei, sizeof(sei));
   with sei do
   begin
     cbSize := SizeOf(sei);
     fMask  := SEE_MASK_NOCLOSEPROCESS;
     Wnd   := handle;
     lpVerb := 'open';
     lpFile := 'iexplore';
     lpParameters := PChar(sURL);
     lpDirectory := #0;
     nShow := SW_SHOWNORMAL;
   end;
   ShellExecuteEX(@sei);//SW_SHOWNOACTIVATE , sau SW_SHOWMINIMIZED sau SW_MINIMIZE
end;

good luck
Avatar of kyrlean

ASKER

Hi ciuly, i'm sory, i posted the wrong values, (Search instead of Sing In ).BTW i was using the right one.
Ok, as i said the problem was parcialy fixed using that extra sleep() on my own code.And i tried the procedure above, replacing the KEYBD_EVENT and it does ok  for yahoo, because "Sign In" matches the yahoo field's values, for Gmail i have to change it for "'Sing in", but.... hotmail is giving me a big headache since 2 months ago because i can't match their Sing in stuff.
It looks like this =>   "   Sign in"  though it's not it. This is the last peace of the puzzle.
Any ideia ?
yes :D

I actually did in my code something like:

[...]
          for m := 0 to Document.forms.Length - 1 do
          begin
            ovElements := Document.forms.Item(m).elements;
     
           try
             s:=ovElements.item(i).Value;
           except
             s:='';
           end;
          if s<>'' then ; // do nothing, just make sure you will have the variable accessible
[...]

and I put a breakpoint on  
if s<>'' then
and put s in the watch. I ran the program and checked the value of s when reached to the button. (do this for ovElements.item(i).type and ovElements.item(i).tagName too, I used "t" respectivly "tt" and put an "if" statement for all.)
after you get to the button in hotmail, just copy/paste the value from the watch and you're done :D
Avatar of kyrlean

ASKER

Well, i'm a little confuse ! I may be doing the wrong thing because i'm getting randon values like "pass" "passport'' ' passportr".
Before i breack my head trying to figure something not necessarily related to the code itself tell me one thing.Doing what are doing now, did you find an effective solution for that. I couldn't cacth it. Call me a stupid there's no problem :-)
what I found is (relevant, not being hidden):

name tagname type
-----------------------
login INPUT text
passwd INPUT password
SI INPUT submit (value is : '    Sign In    ' - apperently 4 spaces in before and after the "sing in" text)
LoginOptions INPUT radio (value 1)
LoginOptions INPUT radion (value 2)
LoginOptions INPUT radion (value 3)

I suggest using the name for compare for all fields, just for the case in which there si a page that has more fields to edit meside user/passw

ovElements.item(i).name ;)
Avatar of kyrlean

ASKER

I'm sure the rest is fine !
This is what i'm really trying to figure...
SI INPUT submit (value is : '    Sign In    ' - apperently 4 spaces in before and after the "sing in" text)

And my question is... Did you try that ?Did it work for you ?

I'll check when i first get a chance !
Thanks buddy !
ASKER CERTIFIED SOLUTION
Avatar of 2266180
2266180
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of kyrlean

ASKER

Ohhh yeahhhh baby ! ! ! !Sorry for the late reply. I didn't get a chance to work on it yestersday. As usual something was still going wrong and then... today i took a closer look at the whole and inserted that extra sleep i told you .It's perfect now. Even minimzed( as expected since there's no necessity of focus  (Keybd_event) ) I really liked the trick you played with it haha ! If we can't find the Tag let's use the Name ;-) Wonderfull !

Check this...https://www.experts-exchange.com/questions/21542279/Points-for-ciuly.html
Thank you very much !