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"