Solved

Filling external Edit fields with text

Posted on 2003-10-29
5
547 Views
Last Modified: 2010-04-03
Hi everyone!

"Lazyness is the mother of 9 out of 10 inventions"...
A friend of mine ;-) has his internet access blocked by a firewall that from time to time asks for a username and a password. Since he is a very good friend of mine I would like to help him by making a program that continuosly scans the desktop windows and when it finds the login window fills automatically the two edit fields and then simulates pressing the OK button.
The window has "Network password" as caption. The window class it's a misterious name: #32770. The two edits have the class names "Edit". Apart from these two edits there are also 2 buttons (OK+Cancel) and a check box ("Remember username and password". It doesn't remember...)
So far I've been able to find the window's handle and the classes of the two edits (for the latter I used an external program). How can I find the handle of the two edits? How can I then press the OK button?

Thanks
Mao
0
Comment
Question by:marusaki
5 Comments
 
LVL 27

Accepted Solution

by:
kretzschmar earned 250 total points
ID: 9641955
if you have the window,
you can use the enumChildWindows-API
to get the handles of the controls

then u could use the wm_settext message to fillin the edits

for pressing ok you can send a enter-key via keybd_event (dialog must have the focos)
or you can send a wm_lbuttondown-message followed by a wm_lbuttonup to
the ok button using its handle

so far the theory
(could be that windows blocks messages
for password-dialogs, because it would be a security-leak,
don't know yet)

if i got time, then a sample may follow

meikl ;-)
0
 
LVL 6

Assisted Solution

by:GloomyFriar
GloomyFriar earned 250 total points
ID: 9642471
Here is a part from my working code:

var
  Form1: TForm1;
  g_w_handle: HWND;
  g_w_cap: string;
  g_stage: longint;
  g_str: array[0..2048] of char;


function EnumChildsFunc(wnd: HWND; lParam: longint): longint; stdcall;
var Res: integer;
    str: array[0..1024] of char;
begin
  Res := GetWindowText(wnd, g_str, 2048);

  case g_stage of
    1: begin
      if g_str[0] = #0 then begin
        if StrComp(@g_str[1], 'First Name:') = 0 then begin
          StrPCopy(str, 'alex');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'Last Name:') = 0 then begin
          StrPCopy(str, 'm');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'Gender:') = 0 then begin
          SendMessage(wnd, CB_SETCURSEL, 1, 0);
        end else if StrComp(@g_str[1], 'Zip / Postal Code:') = 0 then begin
          StrPCopy(str, '22222');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'Occupation:') = 0 then begin
          SendMessage(wnd, CB_SETCURSEL, 2, 0);
        end;
      end else if ((StrComp(@g_str[0], '&Contact me from time to time about specials and new products') = 0) or
                   (StrComp(@g_str[0], '„Ÿ„‚„„‡„‡ >') = 0)) then begin
          SendMessage(wnd, BM_CLICK, 0, 0);
      end;
    end;
    2: begin
      if g_str[0] = #0 then begin
        if StrComp(@g_str[1], 'reate My Own') = 0 then begin
          StrPCopy(str, Form1.Edit1.Text);
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'e&type Password:') = 0 then begin
          StrPCopy(str, '123123');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'Password:') = 0 then begin
          StrPCopy(str, '123123');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end;
      end else if ((StrComp(@g_str[0], 'Create My Own') = 0) or
                   (StrComp(@g_str[0], '&Remember my ID and Password') = 0) or
                   (StrComp(@g_str[0], '„Ÿ„‚„„‡„‡ >') = 0)) then begin
          SendMessage(wnd, BM_CLICK, 0, 0);
      end;
    end;
    3: begin
      if g_str[0] = #0 then begin
        if StrComp(@g_str[1], 'Question we''ll ask:') = 0 then begin
          SendMessage(wnd, CB_SETCURSEL, 2, 0);
        end else if StrComp(@g_str[1], 'our &answer:') = 0 then begin
          StrPCopy(str, '1234567890');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'our &birthday:') = 0 then begin
          StrPCopy(str, '01/01/1975');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end else if StrComp(@g_str[1], 'urrent &Email Address:') = 0 then begin
          StrPCopy(str, 'alexn911@hotmail.com');
          SendMessage(wnd, WM_SETTEXT, 0, integer(@str[0]));
        end;
      end else if (StrComp(@g_str[0], '„Ÿ„‚„„‡„‡ >') = 0) then begin
          SendMessage(wnd, BM_CLICK, 0, 0);
      end;
    end;
  end;
end;



procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  if FindWindowByCap('Window caption') <> HWND(-1) then begin
     g_stage := 1;
    FillMemory(@g_str[0], 2048, BYTE('#'));
    EnumChildWindows(g_w_handle, @EnumChildsFunc, 0);
  end;
end;


function FindWindowByCap(text: string): HWND;
begin
  g_w_handle := HWND(-1);
  g_w_cap := text;
  EnumWindows(@EnumFunc, 0);
  Result := g_w_handle;
end;


function EnumFunc(wnd: HWND; lParam: longint): longint; stdcall;
var str: array[0..2048] of char;
    Res: integer;
begin
   Res := GetWindowText(wnd, str, 2048);
   if ((Res > 0) and
       (CompareStr(g_w_cap, StrPas(str)) = 0)) then begin
     g_w_handle := wnd;
     Result := 0;
   end else begin
     Result := 1;
   end;
end;

0
 
LVL 3

Expert Comment

by:JDuncan
ID: 9643299
listening
0
 

Author Comment

by:marusaki
ID: 9656738
I got the solution. On of the many I think may olve this problem...
I put a Timer on my fom that will scan every 200ms the desktop to find the password window.


function FindControlByNumber(hApp: HWND; ControlClassName: string; EditNr: Integer): HWND;
var
  i: Word;
  hEdit: HWND;
begin
  Result := 0;
  if not IsWindow(hApp) then Exit;
  for i := 0 to EditNr do
  begin
    hEdit := FindWindowEx(hApp, hEdit, PChar(ControlClassName), nil);
    if hEdit = 0 then Continue;
  end;
  Result := hEdit;
end;

function FindWindowByTitle(WindowTitle: string): Hwnd;
var
  NextHandle: Hwnd;
  NextTitle: array[0..260] of char;
begin
  NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  while NextHandle > 0 do
  begin
    GetWindowText(NextHandle, NextTitle, 255);
    if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
    begin
      Result := NextHandle;
      Exit;
    end
    else
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  end;
  Result := 0;
end;

procedure TfrmMain.tmrAuthTimer(Sender: TObject);
var
  Hand: HWND;
  EdtHand: HWND;
  BtnHand:HWND;
begin
  Hand := FindWindowByTitle('Password di rete');
  if Hand > 0 then
  begin
    tmrTimer.Enabled := False;

    // find the first Edit
    EdtHand := FindControlByNumber(Hand,'Edit',1);
    SendMessage(EdtHand, WM_SETTEXT, 0, Integer(PChar('myuser')));

    // find the second Edit
    EdtHand := FindControlByNumber(Hand,'Edit',2);
    SendMessage(EdtHand, WM_SETTEXT, 0, Integer(PChar('mypass')));

   // find the OK button (the checkbox has also the ClassName 'Button' so i skip it...)
    BtnHand := FindControlByNumber(Hand,'Button',2);
    SendMessage(BtnHand, WM_LBUTTONDOWN, 0, 0);  // simulate pressing the button
    SendMessage(BtnHand, WM_LBUTTONUP, 0, 0);

    tmrTimer.Enabled := True;
  end;
end;

It works like a dream! Now I'm working on adding a TWebBrowser and a second timer that every 10 minutes will try to open a link thus making the authentication window to pop up even if I'm not navigating in Internet Explorer. In this way I will have a pseudo-permanently open internet connection. Well, my friend will...
0
 

Author Comment

by:marusaki
ID: 9656789
I forgot to post my source of inspiration
  http://www.swissdelphicenter.com/en/showcode.php?id=327

Anyway, thanks meikl and GloomyFriar! I got some good tips from you.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
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…
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

910 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

23 Experts available now in Live!

Get 1:1 Help Now