C
C#2y ago
Owen

❔ Issue with GlobalMouseKeyHook / Global Hotkeys.

I am using: https://github.com/gmamaladze/globalmousekeyhook in one of my C# console applications to receive keypresses when the console is out of focus. This works in one of my applications - but when attempting to use the same code in a new project, the key presses are not detected at all. Not sure what the problem could be here. Any ideas? Here's the implementation i'm using in both programs.
using Gma.System.MouseKeyHook;

public class CreateHotkeyEvent
{
public static void Do()
{
Hook.GlobalEvents().KeyPress += (sender, e) =>
{
if (e.KeyChar == ')')
{
Console.WriteLine("stop");
ConsoleExtensions.ChangeRunningState();
}
else if(e.KeyChar == '(')
{
Console.WriteLine("hide");
ConsoleExtensions.ShowHideWindow();
}
};
}
}
using Gma.System.MouseKeyHook;

public class CreateHotkeyEvent
{
public static void Do()
{
Hook.GlobalEvents().KeyPress += (sender, e) =>
{
if (e.KeyChar == ')')
{
Console.WriteLine("stop");
ConsoleExtensions.ChangeRunningState();
}
else if(e.KeyChar == '(')
{
Console.WriteLine("hide");
ConsoleExtensions.ShowHideWindow();
}
};
}
}
GitHub
GitHub - gmamaladze/globalmousekeyhook: This library allows you to ...
This library allows you to tap keyboard and mouse, detect and record their activity even when an application is inactive and runs in background. - GitHub - gmamaladze/globalmousekeyhook: This libra...
35 Replies
Buddy
Buddy2y ago
What are you making?
Owen
OwenOP2y ago
A FiveM development tool. Will have a bunch of different development things I need on the fly which can be accessed without un-focusing the game.
Groophy
Groophy2y ago
GitHub
GitHub - HavenDV/H.Hooks: Contains LowLevelKeyboardHook and LowLeve...
Contains LowLevelKeyboardHook and LowLevelMouseHook. - GitHub - HavenDV/H.Hooks: Contains LowLevelKeyboardHook and LowLevelMouseHook.
Groophy
Groophy2y ago
try this one
Owen
OwenOP2y ago
Thanks for your suggestion. Here's my implementation, however nothing is written to the console when the keys are pressed.
using H.Hooks;

namespace GTAToolkit.Hotkeys
{
public class CreateHotkeyEvent
{
public static void Do()
{
/*Hook.GlobalEvents().KeyPress += (sender, e) =>
{
if (e.KeyChar == ')')
{
Console.WriteLine("stop");
ConsoleExtensions.ChangeRunningState();
}
else if(e.KeyChar == '(')
{
Console.WriteLine("hide");
ConsoleExtensions.ShowHideWindow();
}
};*/

using var keyboardHook = new LowLevelKeyboardHook();
keyboardHook.Down += (_, args) =>
{
if (args.Keys.Are(Key.Control, Key.LeftShift))
{
Console.WriteLine("key detected");
}
};

keyboardHook.Start();

}
}
}
using H.Hooks;

namespace GTAToolkit.Hotkeys
{
public class CreateHotkeyEvent
{
public static void Do()
{
/*Hook.GlobalEvents().KeyPress += (sender, e) =>
{
if (e.KeyChar == ')')
{
Console.WriteLine("stop");
ConsoleExtensions.ChangeRunningState();
}
else if(e.KeyChar == '(')
{
Console.WriteLine("hide");
ConsoleExtensions.ShowHideWindow();
}
};*/

using var keyboardHook = new LowLevelKeyboardHook();
keyboardHook.Down += (_, args) =>
{
if (args.Keys.Are(Key.Control, Key.LeftShift))
{
Console.WriteLine("key detected");
}
};

keyboardHook.Start();

}
}
}
canton7
canton72y ago
I'm not sure whether it's relevant, but you are disposing keyboardHook straight after calling Start on it
Owen
OwenOP2y ago
Seems to have fixed it - thanks for your spot.
canton7
canton72y ago
Yuckyuckyuck. There's no need to sleep the entire thread Just remove the using. You should probably make CreateHotkeyEvent IDisposable, and dispose the keyboardHook when CreateHotkeyEvent is disposed. That way the rest of you application has a way to remove the hook
Owen
OwenOP2y ago
Totally agree - was just my way to test. I will look into a clean implementation now
Groophy
Groophy2y ago
Already canton7 said if you want to use using you must to create body like
using (var keyboardHook = new LowLevelKeyboardHook())
{
keyboardHook.Down += (_, args) =>
{
if (args.Keys.Are(Key.Control, Key.LeftShift))
{
Console.WriteLine("key detected");
}
};
}

keyboardHook.Start();
using (var keyboardHook = new LowLevelKeyboardHook())
{
keyboardHook.Down += (_, args) =>
{
if (args.Keys.Are(Key.Control, Key.LeftShift))
{
Console.WriteLine("key detected");
}
};
}

keyboardHook.Start();
because when body end will dispose your class
canton7
canton72y ago
Uh, that's not what I said at all. That's even worse than the using var, because that disposes the keyboardHook before you can even call Start on it!
sibber
sibber2y ago
does gta allow this in their TOS?
Owen
OwenOP2y ago
Program is completely external. It does nothing with the live game. Simply creates its own files that can be later used within fivem It doesn’t touch or interact with the game in any way. It is simply a tool to simplify file generation, and other things required in FiveM development What are your thoughts on this implementation?
using GTAToolkit.Extensions;
using H.Hooks;

namespace GTAToolkit.Hotkeys
{
public class CreateHotkeyEvent
{
public static LowLevelKeyboardHook keyboardHook = new LowLevelKeyboardHook();
public static void Do()
{
keyboardHook.Down += (_, args) =>
{
if (args.Keys.Are(Key.Shift, Key.D0))
{
// Shows/hides window via ')' hotkey
ConsoleExtensions.ShowHideWindow();
}
};
keyboardHook.Start();
}
}
}
using GTAToolkit.Extensions;
using H.Hooks;

namespace GTAToolkit.Hotkeys
{
public class CreateHotkeyEvent
{
public static LowLevelKeyboardHook keyboardHook = new LowLevelKeyboardHook();
public static void Do()
{
keyboardHook.Down += (_, args) =>
{
if (args.Keys.Are(Key.Shift, Key.D0))
{
// Shows/hides window via ')' hotkey
ConsoleExtensions.ShowHideWindow();
}
};
keyboardHook.Start();
}
}
}
I then have another method to detect console closing which will Dispose the public keyboardHook.
canton7
canton72y ago
Eh. I don't like that things are static, or that someone can call Do twice which will break things, or that people have to dispose the keyboardHook member even though they used the CreateHotkeyEvent class to start it At the very least, keyboardHook should be readonly / a getter-only property, so people can't re-assign it
Owen
OwenOP2y ago
I'm not yet familiar with
IDisposable
IDisposable
- so I wasn't able to fully put your above recommendation to practice. Maybe I will do some research if you think an alternative method involving this would be better. Sounds correct, I will make this change now.
sibber
sibber2y ago
id use the raw input api rather than low level hooks
Owen
OwenOP2y ago
This does look good - thank you muchly. I'm pretty happy using low level hooks here as it seems to work, just needs solid implementation. I'm going to save the above code snippet though, and if I encounter any issues - i'll be switching over.
sibber
sibber2y ago
definitely look into IDisposable its basically just an interface that has a special keyeord
Jester
Jester2y ago
if IDisposable, call Dispose on the object when you dont need it anymore
sibber
sibber2y ago
you dispose unmanaged resources in the Dispose method and you clearly have unmanaged resources
Owen
OwenOP2y ago
Sounds like essentially what I have written above - but done correctly haha. I will look into it now.
sibber
sibber2y ago
and don't make anything static
canton7
canton72y ago
and you clearly have unmanaged resources
Nope, no unmanaged resources here LowLevelKeyboardHook is very much managed
sibber
sibber2y ago
is it, my bad
canton7
canton72y ago
An unmanaged resource is something like an IntPtr to native memory, which can't free itself A reference to another C# class is managed
sibber
sibber2y ago
yeah I'm aware
canton7
canton72y ago
LowLevelKeyboardHook probably owns unmanaged resources, but they're its responsibility
Jester
Jester2y ago
you could also unregister the hotkey but thats usually not needed
sibber
sibber2y ago
oh i thought he was writing LowLevelKeyboardHook
sibber
sibber2y ago
ah if this is just for hotkeys why not just use RegusterHotkey
Jester
Jester2y ago
i cleaned it up a little and put it on github https://github.com/QubitTooLate/Snippies/blob/main/HotKeys.cs
Owen
OwenOP2y ago
Thank you very much! Thank you others also, appreciate the help greatly.
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server