|
|
Comments and Discussions
|
|
 |

|
sir,If I want to hook combination key,such as Shift+A,
the setup code gkh.HookedKeys.Add(Keys.A & Keys.Control);
does't work, please help me.
|
|
|
|

|
works on c# 2010 express, simple to use, thanks
|
|
|
|
|

|
Hi ,
Is it possible to run this without the .NET framework installed on the Windows system.
If not , then let us think of alternates.
A low level hook should be pretty compatible every place.
|
|
|
|

|
I am unable to send small letters using SendKeys.Send() with SHIFT modifier key pressed. My app needs (for example) if the user presses K button "a" should be sent and if he presses SHIFT+K, "b" should be sent. The code is:
void gkh_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.K)
{
if (Control.ModifierKeys == Keys.Shift)
SendKeys.Send("b");
else
SendKeys.Send("a");
}
e.Handled == true;
}
But it sends "B" (Capital letter) instead of "b", that is the SHIFT key changes the sent keystroke "b" to uppercase. This happens even after adding Keys.Shift to the hook.
I tried many approaches including using e.SupressKeyPress, SendKeys("b".toLower()) and putting above code in KeyUp event but in vein.
Pls help me, I am very frustated, my application developement is struck at this point.
modified on Saturday, March 26, 2011 11:19 AM
|
|
|
|

|
Hi ,
Can you please give some light on how to use this to make is case sensitive and
also to detect symbols like " , .;: / ? etc.
Tried using ASCII value , but e.Modifier , e.Shift are always None.
And No Idea how to approach for the special symbol keys , and to get the ones Shift + numbers.
Minor modifications or guidelines , please provide any insight.
Thanks
Aces J
|
|
|
|

|
They seem not to be working. It always says Modifiers None even if i am holding Shift/Ctrl/Alt.
|
|
|
|

|
Great Code!
Thank you a lot!
|
|
|
|

|
hi StormySpike
tnx for your great atricle.
but i have a problem,actually when i use keyboardhook to hook a key and send it for active window with sendkey() i have this error:
A callback was made on a garbage collected delegate of type 'keyboardhook!Utilities.globalKeyboardHook+keyboar dHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
most time when i press a key(that i hooked it) and press a key and keep it down it for a long time.(i press a key and keep my finger on that).
and this id my code:
************
gkh.HookedKeys.Add(Keys.OemPipe);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
***********
void gkh_KeyDown(object sender, KeyEventArgs e)
{
if (stringgetName() == "00000429")
{
Char ch_Ye = (Char)1740;
Char ch_K = (Char)1705;
Char ch_P = (Char)1662;
Char ch_Zh = (Char)1688;
switch (e.KeyCode)
{
case Keys.D:
System.Windows.Forms.SendKeys.Send(ch_Ye.ToString());
break;
case Keys.OemSemicolon:
System.Windows.Forms.SendKeys.Send(ch_K.ToString());
break;
case Keys.Oemtilde:
System.Windows.Forms.SendKeys.Send(ch_P.ToString());
break;
case Keys.OemPipe:
System.Windows.Forms.SendKeys.Send(ch_Zh.ToString());
break;
}
e.Handled = true;
}
}
tnx for your attention.
و این منم زنی تنها در آستانه فصلی سرد...
|
|
|
|

|
Hi Guys,
Does anyone know how to apply this code to Windows Service on Windows 7.
Windows Service is unable to detect KeyEventHandler in the code even though
I added Windows Form in the NameSpace.
Thank you for any help provided.
mk77
|
|
|
|

|
How do I use this for Windows Service?
I tried it on Win Service but it does not recognise
the keyevent handler
mk77
|
|
|
|
|

|
The sample works fine but in more sophisticated mdi interface you get a CallbackOnCollectedDelegate Exception.
To avoid this porblem just change code.
Replace
public void hook() {
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}
by
public void hook() {
IntPtr hInstance = LoadLibrary("User32");
// Avoid CallbackOnCollectedDelegate Exception
// when calling delegates from unmanaged code
hkbProc = new keyboardHookProc(hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hkbProc, hInstance, 0);
}
Jean-Michel Grange
|
|
|
|

|
This is the simplest and neatest hook code I have seen. Can you make one like that to hook keyboards too?
|
|
|
|

|
Thanks StormySpike...
Helped me to learn a lot..
|
|
|
|

|
can also do Ctrl + alt + i? :(
|
|
|
|

|
How do you add characters to the hook like danish æ, ø and å. Or other european special characters?
|
|
|
|

|
Is it possible to do with all keys? Also KeyPress event would be nice
|
|
|
|

|
error garbage collected delegate but solution in ocmments
|
|
|
|

|
it crash when we type very fast
|
|
|
|

|
Is there a way to capture a key combination like CTRL+ALT+A, where those three keys are pressed simultaneously?
|
|
|
|

|
Have a look at your marshalling! (Attributes) Your code can lead to some (seldom but nasty) errors.
So sorry for the bad vote but your code seems to be reused by a lot of people, i will revote if you improve your code.
A good site is: http://www.pinvoke.net[^]
Maybe you are also interested in the way I get the Instance handle for the process containing the callback.
Have a look at the code I use for a keyboard hook:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Common
{
#region CLASS GlobalKeyboardHook
public class GlobalKeyboardHook
{
#region TYPES
#region CLASS KeyboardHookStruct
[StructLayout(LayoutKind.Sequential)]
class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
#endregion
#region DELEGATE HookProc
protected delegate int HookProc(int nCode, int wParam, IntPtr lParam);
#endregion
#endregion
#region CONSTANTS
const int WH_KEYBOARD_LL = 13;
const int WH_KEYBOARD = 2;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const byte VK_SHIFT = 0x10;
const byte VK_CAPITAL = 0x14;
const byte VK_NUMLOCK = 0x90;
const byte VK_LSHIFT = 0xA0;
const byte VK_RSHIFT = 0xA1;
const byte VK_LCONTROL = 0xA2;
const byte VK_RCONTROL = 0x3;
const byte VK_LALT = 0xA4;
const byte VK_RALT = 0xA5;
#endregion
#region VARIABLES
bool m_bHookActive;
int m_iHandleToHook;
protected HookProc m_hookproc;
#endregion
#region EVENTS
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
public event KeyPressEventHandler KeyPress;
#endregion
#region CONSTRUCTION & DESTRUCTION
~GlobalKeyboardHook()
{
Unhook();
}
#endregion
#region PROPERTIES
public bool HookActive
{
get { return m_bHookActive; }
}
#endregion
#region METHODS
public bool Hook()
{
if(!m_bHookActive)
{
m_hookproc = new HookProc(HookCallbackProcedure);
IntPtr hInstance = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
m_iHandleToHook = SetWindowsHookEx(
WH_KEYBOARD_LL,
m_hookproc,
hInstance,
0);
if(m_iHandleToHook != 0)
{
m_bHookActive = true;
}
}
return m_bHookActive;
}
public void Unhook()
{
if(m_bHookActive)
{
UnhookWindowsHookEx(m_iHandleToHook);
m_bHookActive = false;
}
}
protected virtual void OnKeyDown(KeyEventArgs kea)
{
if(KeyDown != null)
KeyDown(this, kea);
}
protected virtual void OnKeyUp(KeyEventArgs kea)
{
if(KeyUp != null)
KeyUp(this, kea);
}
protected virtual void OnKeyPress(KeyPressEventArgs kpea)
{
if(KeyPress != null)
KeyPress(this, kpea);
}
#endregion
#region EVENTHANDLER
int HookCallbackProcedure(int nCode, int wParam, IntPtr lParam)
{
bool bHandled = false;
if(nCode > -1 && (KeyDown != null || KeyUp != null || KeyPress != null))
{
KeyboardHookStruct khs = (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
bool bControl = ((GetKeyState(VK_LCONTROL) & 0x80) != 0) || ((GetKeyState(VK_RCONTROL) & 0x80) != 0);
bool bShift = ((GetKeyState(VK_LSHIFT) & 0x80) != 0) || ((GetKeyState(VK_RSHIFT) & 0x80) != 0);
bool bAlt = ((GetKeyState(VK_LALT) & 0x80) != 0) || ((GetKeyState(VK_RALT) & 0x80) != 0);
bool bCapslock = (GetKeyState(VK_CAPITAL) != 0);
KeyEventArgs kea = new KeyEventArgs((Keys) (khs.vkCode |
(bControl ? (int) Keys.Control : 0) |
(bShift ? (int) Keys.Shift : 0) |
(bAlt ? (int) Keys.Alt : 0)));
if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
OnKeyDown(kea);
bHandled = kea.Handled;
}
else if(wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
{
OnKeyUp(kea);
bHandled = kea.Handled;
}
if(wParam == WM_KEYDOWN && !bHandled && !kea.SuppressKeyPress)
{
byte[] abyKeyState = new byte[256];
byte[] abyInBuffer = new byte[2];
GetKeyboardState(abyKeyState);
if(ToAscii(khs.vkCode, khs.scanCode, abyKeyState, abyInBuffer, khs.flags) == 1)
{
char chKey = (char) abyInBuffer[0];
if((bCapslock ^ bShift) && Char.IsLetter(chKey))
chKey = Char.ToUpper(chKey);
KeyPressEventArgs kpea = new KeyPressEventArgs(chKey);
OnKeyPress(kpea);
bHandled = kea.Handled;
}
}
}
if(bHandled)
return 1;
else
return CallNextHookEx(m_iHandleToHook, nCode, wParam, lParam);
}
#endregion
#region EXTERN
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern short GetKeyState(int vKey);
[DllImport("user32.dll")]
static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion }
#endregion }
btw: This is .NET not Java - the convention is: type names start with capital letters...
|
|
|
|

|
I've made a program using this hook and on about the 40th second I get an exception:
A callback was made on a garbage collected delegate of type 'SuperLogger!Utilities.globalKeyboardHook+keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
That's quite weird. Any ideas?
|
|
|
|

|
Hi,
First of all, thanks for sharing this code!
Second: I got a problem using this code, I'm hooking some "normal" keys (like A, S, Q...) and the alt key. After a while (30-240 minutes), my application crashes. I surrounded all of my code with try-catches and debug output in the catch clause, so i'm almost sure its not my code that causes the crash (bold statement, I know ... not to be taken too seriously).
The only piece of information I found so far: The crash seems to occur shortly after using the arrow keys (which I did not hook).
My system: Win XP SP3, 32 Bit, german language
UPDATE: After testing some more, its not bound to the arrow keys ... it happens with all keys. I had some more crashes today that occured while I was typing.
modified on Wednesday, April 7, 2010 11:16 AM
|
|
|
|

|
I need to use the F1 in my application, and ive tried e.handled, but everytime ive hit F1, it brings up help.
|
|
|
|

|
When I hook keys, and then press them, the app locks up for a second or two, then resumes. why does it do this?
|
|
|
|

|
Hi, i'm trying to make my program pick up any key and write it in a text file when i press F6, then, i want the text file to be read and all the text from it put into a TextBox on the form by pressing F7. I've looked at numerous posts such as the one with the _hookAll thing, but when i type ANYTHING on a text field with this function, nothing happens. the text doesnt even appear.
I'm making a spammer (for experimental reasons) and everything works. I want the user to be able to set a new message without going back to the Form (by pressing F6 to activate, F7 to set).
I might not even have to use streamwriter/reader to do this, it just seems an easier option for me.
So can someone tell me why and how to stop the program disabling my keyboard?
Thanks!
|
|
|
|

|
WOW! This is PERFECT!!! Short, representative, well organized and after I changed some things I have read from the posts it's WORKING! Exactly what I needed, thanks!
modified on Friday, January 1, 2010 10:00 AM
|
|
|
|

|
Hi, I got the following error:
System.NullReferenceException: Object reference not set to an instance of an object.
at Utilities.globalKeyboardHook.CallNextHookEx(IntPtr idHook, Int32 nCode, Int32 wParam, keyboardHookStruct& lParam)
at Utilities.globalKeyboardHook.hookProc(Int32 code, Int32 wParam, keyboardHookStruct& lParam) in c:\Documents and Settings\Marius Utheim\Mine dokumenter\SharpDevelop Projects\Useful stuff\globalKeyboardHook.cs:line 109
at System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
It seems to happen if I press two keys at the same time, or almost simultaneously. Do you know how to fix it?
|
|
|
|

|
Hi, I tried the sample and it worked well so without further thought I implemented it in my app. However when a key is pressed... i get the error "object reference not set to an instanc eof an object" now before you go jumping to conclusions let me tell you WHERE this error occurs... on the Application.Run(new Form1()); line in the main program file...
System.NullReferenceException: Object reference not set to an instance of an object.
at ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
at ThreadContext.RunMessageLoopInner
at ThreadContext.RunMessageLoop
at System.Windows.Forms.Application.Run
This will occur whenever ANY key is pressed, and all I need to do is create an instance of your class and it will happen.
Now I have gotten this error before in this app, it uses directx's audio object, and upon trying to stop an already stopped audio object this weird error would happen.. therefore I'm thinking the existance of these two things are to blame.. not that it makes much sense though...
|
|
|
|

|
Hello, I'm using your great hook class, and it's been responding great, until I needed to use Settings in Visual Studio!
Basically, I allow the user to save his settings; the settings of the modified key functions.
Just adding this line in the code generates an annoying error:
if (Properties.Settings.Default.DisableAll == false) { }
The error I'm getting is:
A callback was made on a garbage collected delegate of type 'key preview!Utilities.globalKeyboardHook+keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
This is really stopping me from further progress, and I am completely unable to do anything about it, even MSDN experts are not capable to providing solutions!
|
|
|
|

|
Hi
I have a question in my application , when i used ur code, how i contact you?
|
|
|
|

|
Great Code, thanks!
I was trying to capture Alt+Q. I was able to get "Alt" through Control.ModifierKeys. However, when casting lParam.vkCode to (Keys), I constantly got "MButton | Space | F17", and vkCode was always 164. (I was expecting to get "Q")
I tried with other key combinations, stil getting the same thing. Does anyone knoow what could have caused this and how to resolve it?
Thanks a lot!
|
|
|
|

|
As another user has posted below, at random keystroke intervals, it stops capturing them? Any idea as to why?
|
|
|
|

|
hi
i'm trying to get it to work in wpf.
i have only one problem that is the keys..
using system.windows.input.key
the problem is in here:
Key key = (Key)lParam.vkCode;
i get a code that is for windows form keys..
what do i have to change, to work with the right key in wpf..
|
|
|
|

|
So i cant make it unhook the keyboard, and when i press a button only the program registers it Any way to fix this?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Utilities;
using System.IO;
namespace KeyLog
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
globalKeyboardHook g_hk = new globalKeyboardHook();
bool load = false;
private void Form1_Load(object sender, EventArgs e)
{
}
void g_hk_KeyDown(object sender, KeyEventArgs e)
{
log_view.Items.Add("Down\t" + e.KeyCode.ToString());
e.Handled = true;
}
private void btn_load_Click(object sender, EventArgs e)
{
if (load == false)
{
g_hk.hook();
foreach (object key in Enum.GetValues(typeof(Keys))) g_hk.HookedKeys.Add((Keys)key);
g_hk.KeyDown += new KeyEventHandler(g_hk_KeyDown);
load = true;
}
}
private void btn_dump_Click(object sender, EventArgs e)
{
string time = DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();
string dump = " ";
for (int i = 0; log_view.Items.Count > i; i++)
{
log_view.SelectedIndex = i;
dump += log_view.Text.ToString() + Environment.NewLine;
}
StreamWriter d_ump = new StreamWriter(@Application.StartupPath + "\\" + time + ".txt");
d_ump.Write(dump);
d_ump.Close();
}
private void button1_Click(object sender, EventArgs e)
{
g_hk.unhook();
}
}
}
|
|
|
|

|
Im getting the following error while trying to use this class in my app
A callback was made on a garbage collected delegate of type 'TestFlashCommunication!Utilities.globalKeyboardHook+keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss.
How can I prevent this from happening?
|
|
|
|

|
I want to use all they keys to be going through my keyboard hook application, and not just A and B. How can I do that? (Except some key combination like Ctrl. Shift Esc. etc. )
Thanks !!
|
|
|
|

|
Hi,
I used your example to capture keystrokes. It captures them globally without any problem, but only upto a certain number of key strokes(which is random). For example, sometimes when I have pressed 280 keys it stops capturing. Sometimes 236, 182 rarely, but even 8 !! I know it might not be related to these numbers at all. (I'm running Windows Vista) but what makes it stop capturing key strokes?
Thanks !
|
|
|
|
|

|
Critically buggy implementation
|
|
|
|

|
Hello,
I would like to replace certain keystrokes with other key(s).
Examples:
I would like to send two "q" keystrokes when the user presses "a".
A device sends the key sequence, -7.134 enter. I would like to replace the enter after the number with one or two tabs.
I have tried.
} else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null)) {
if (key == Keys.Enter)
{
KeyUp(this, kea);
SendKeys.Send("{TAB}");
return -1;
}
KeyUp(this, kea);
return 1;
}
but it either only works the first time or not at all.
I have also tried SendKeys.Send("{TAB}"); in KeyUp but seems to only work the first time.
Any help on this would be appreciated?
Thanks,
PS. Please respond here as my email does not work.
|
|
|
|

|
Hello StormySpike,
I know it's off topic, but I see you've worked with C# and clarion both, so maybe you can answer me this.
Can I get a clarion MDI child window to display in C# MDI container? If I can, then how? Please give me a hint, advice, and in best case, code snippet that would do it.
Thanks
|
|
|
|

|
In your text you say that the threadid can be zero.
And it works in your demo application. But in my real application,
it gives a NullReferenceException when any key is pressed.
I tried putting a thread id by AppDomain.GetCurrentThreadId() and Thread.CurrentThread.ManagedThreadId
But on both case the hook fails to register because I added a check for zero on the hhook after SetWindowsHookEx.
Many articles debate about what thread id to put there.
What suggestions does anybody have?
Wayne
|
|
|
|

|
Hi
I want to use this to see how often certain keys are used in everyday use. The keys I choose to hook become unavailable though. eg. if I hook keys.A then i cannot type A in notepad anymore.
I want to log keys but without losing their functionality.
Thanks
|
|
|
|

|
Hi,
I'm trying to grab a key on a web page which isn't a form. If I don't put in the following:
using System.Windows.Forms;
then I get error messages regarding 'KeyEventArgs' (see below).
error CS0246: The type or namespace name 'KeyEventArgs' could not be found (are you missing a using directive or an assembly reference?)
If I DO put in the "using" statement, then I get errors such as the following:
error CS0104: 'BorderStyle' is an ambiguous reference between 'System.Web.UI.WebControls.BorderStyle' and 'System.Windows.Forms.BorderStyle'
Can I only use your code if I'm doing Windows forms?
Thanks in advance.
|
|
|
|

|
Does anyone have any examples of using the IEnumerable type for the HookedKeys.addrange method? I'm trying to find a nice way to either hook all keyboard presses, or create an array which does a large number of them without having to "add(keys.a), add(keys.b),... etc etc..."
|
|
|
|

|
Hi,.
I want to stop Win key...shiftkey (All) excluding Up n Down arrow. also want to disabled mouse event How hould I overcome that issue.Where we want to adjust.??
Please,..
Ur cooperate is appreciated.!
|
|
|
|

|
The download links to the code and example files sends me to an error page.
|
|
|
|

|
how to use this if i want to hook let's say ctrl + A, or ctrl + alt + b? Thanks
darkmaster35
|
|
|
|

|
I looked some time to understand why my project didnt work in VB.NET. Now I had your project to test and I saw that VS hat an flag "nicht verwaltetes Debuggen aktivieren". And I saw some nice ways in your code too. Like raising events from a MouseHandler.
I've done it in German.
Thanks for your work and regards
Timo
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
A simple description and sample of creating a global low level keyboard hook in C#
| Type | Article |
| Licence | CPOL |
| First Posted | 30 May 2007 |
| Views | 282,891 |
| Downloads | 19,415 |
| Bookmarked | 126 times |
|
|