I wonder if the FProcessInfo.dwThreadId is actually a threadID or a thread
handle (they are not the same).
Failing that I would suggest it is a security issue, or you just cannot
reference the threadID for a thread the belongs to another process.

Either way there probably not much you can do.

I suspect the SetWindowHook will only accept a threadid from your current
process (undocumented feature??).
I suspect it depends where windows applies the hook - for a system wide hook
it is probably applied directly to the keyboard (before the message is sent
to any thread message queue), for a thread specific hook it is probably
applied to the thread message queue.

You will probably have to filter messages based on threadID (or window
handle)  (somehow ...)

Myles.

-----Original Message-----
From: Donovan J. Edye [mailto:[EMAIL PROTECTED]]
Sent: Thursday, October 05, 2000 11:10 AM
To: Multiple recipients of list delphi
Subject: [DUG]: [Q] Embedded DOS Prompt Part II -- SetWindowsHookEx()


G'Day,

> Paul Ritchie said:
> SetWindowsHookEx.
> Hours of fun - guaranteed.

And how right he was..... ;-( After playing with this for a while I still
have one __MAJOR__ frustration. Namely that I cannot seem to be able to set
the hook to be for the cmd.exe thread that I kick off with a
CreateProcess(). I have a DLL with the hook procedure in it, and a
standalone EXE that simply invokes a CMD.EXE via a CreateProcess() and then
sets a keyboard hook to capture all the keystrokes in the console window.

(See code snippets below)

With the following call I should get the hook registered for the cmd.exe
that I
have started with CreateProcess(). In fact I do get FKeyHook > 0 returned
from
the call below, but the KeyTrapMsgHook() does not fire. (No ShowMessage)


      FKeyHook := SetWindowsHookEx(
        WH_KEYBOARD, // type of hook to install
        @KeyTrapMsgHook, // address of hook procedure
        FDLLHandle,
        FProcessInfo.dwThreadId
        );


If I however do:

      FKeyHook := SetWindowsHookEx(
        WH_KEYBOARD, // type of hook to install
        @KeyTrapMsgHook, // address of hook procedure
        FDLLHandle,
        0   //<- No ThreadID so system wide
        );

then I get a system wide hook as expected. ie KeyTrapMsgHook() fires. (Is
ShowMessage)

Just to prove that I was not insane I did:

      FKeyHook := SetWindowsHookEx(
        WH_KEYBOARD, // type of hook to install
        @KeyTrapMsgHook, // address of hook procedure
        FDLLHandle,
        GetCurrentThreadID   //<-- Application thread
        );

And this works for my application thread. So __why__ does it not work for a
cmd.exe created with CreateProcess()? What am I missing here? Something
__really__ subtle I am sure....


TIA


A DLL containing the hook function:

library KH;

uses
  SysUtils,
  Classes,
  Dialogs,
  Windows;

var
   FKeyHook : HHook;

{$R *.RES}

function KeyTrapMsgHook(nCode: Integer; wParam, lParam: Longint): Longint;
stdcall;
var
  KeyDown: Boolean;
   //  IsAlt : Boolean;
  //WasDown: Boolean;
  //OkToTrap: Boolean;
  //ParentForm: TCustomForm;
begin
  result := 0;
  if nCode < 0 then
  begin
    result := CallNextHookEx(FKeyHook, nCode, wParam, lParam);
    Exit;
  end else
  begin
       ShowMessage(Chr(wparam));
    result := CallNextHookEx(FKeyHook, nCode, wParam, lParam);
    Exit;
  end;
end;

exports KeyTrapMsgHook name 'KeyTrapMsgHook';

begin
end.


Click from EXE that kicks off the cmd process

procedure TForm1.Button2Click(Sender: TObject);
//var
  //StartupInfo: TStartupInfo;
  //ProcessInfo: TProcessInformation;
begin
  //Init the DLL containing the hook function
  FDLLHandle := LoadLibrary('KH.DLL');

  if FDLLHandle <> 0 then
  begin
    @KeyTrapMsgHook := GetProcAddress(FDLLHandle, 'KeyTrapMsgHook');
  end else
    ShowMessage('Oops');

  //Now kick off the console
  FillChar(FStartupInfo, SizeOf(StartupInfo), 0);
  with FStartupInfo do
  begin
    wShowWindow := SW_SHOWMAXIMIZED;
    lpTitle := PChar('My_Console');
    dwFlags := STARTF_USEPOSITION or STARTF_USESIZE;
    FStartupInfo.cb := SizeOf(FStartupInfo);
  end;

  try
    if CreateProcess('c:\winnt\system32\cmd.exe', nil, nil, nil, TRUE, 0,
nil,
      'c:\winnt\system32\', FStartupInfo, FProcessInfo) then
    begin
      //Created the process
      //Find the handle
      repeat
        FPromptHandle := FindWindow(nil, 'My_Console');
      until FPromptHandle <> 0;
      Windows.SetParent(FPromptHandle, panPrompt.Handle);
      //Install the key hook
      FKeyHook := 0;
      FKeyHook := SetWindowsHookEx(
        WH_KEYBOARD, // type of hook to install
        @KeyTrapMsgHook, // address of hook procedure
        // -- MainInstance, // handle of application instance
        FDLLHandle,
//        0 // identity of thread to install hook for
        FProcessInfo.dwThreadId
        );
//      FKeyHook := Get_KeyHook(FProcessInfo.dwThreadId, MainInstance);
      ShowMessage(IntToStr(FKeyHook));
    end else ShowMessage('Error creating process : ');
  except

  end;
end;

------------------------------------------------------------------------
--Donovan [[EMAIL PROTECTED]]
Donovan J. Edye [www.edye.wattle.id.au]
Namadgi Systems, Delphi Developer [www.namsys.com.au]
Voice: +61 2 6285-3460 Fax: +61 2 6285-3459
TVisualBasic = Class(None);
Heard just before the 'Big Bang': "...Uh Oh...."
------------------------------------------------------------------------
GXExplorer [http://www.gxexplorer.org] Freeware Windows Explorer
replacement. Also includes freeware delphi windows explorer components.
------------------------------------------------------------------------

---------------------------------------------------------------------------
    New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
                  Website: http://www.delphi.org.nz
To UnSub, send email to: [EMAIL PROTECTED] 
with body of "unsubscribe delphi"
---------------------------------------------------------------------------
    New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
                  Website: http://www.delphi.org.nz
To UnSub, send email to: [EMAIL PROTECTED] 
with body of "unsubscribe delphi"

Reply via email to