2

I have created a windows service in c#. How can I call a function whenever a key is pressed, and in this function get the value of the key. I need it for both key up and key down.

My goal is to send an email if a certain series of keys were pressed. For example if you press h-e-l-l-o, no matter where you type it even on the desktop, the program should send the email.

Also, it's ok for me to implement it in another way. I need a program that runs in the background and do something when a key is pressed.

How can I do such thing? An example would be helpful.

צח חורי
  • 371
  • 1
  • 3
  • 9
  • 4
    since a windows service runs in the background, in non-interactive mode, how are you expecting that to work? Clearly you want to give some instructions to the service at a certain time...but you'll have to think of a different way of doing that. – ADyson May 12 '19 at 20:36
  • Can you suggest me another solution? – צח חורי May 12 '19 at 20:42
  • 2
    Possibly. But you'd have to explain more about what the situation is and what you want to achieve. What should the service do when it receives this input? And why did you want to give it via keyboard specifically? Normally a user should not need to control a service in this way, it is intended to run automatically. Is this for some debugging or manually triggering a specific process, or what? Like I said, if can explain the overall goal then maybe we can find an alternative way. – ADyson May 12 '19 at 20:59
  • I want, for example, to send an email if a certain series of keys were pressed. For example if you type "hello" no matter where you type it even on the desktop, the program will send the email. – צח חורי May 12 '19 at 21:07
  • you would need a separate program running in the desktop area which would log keystrokes (beware however that such software is often considered to be spyware or malware by the operating system, as they are often used to try and steal passwords etc, unless you make it very specific to handle only certain hotkeys). It would then have to send an event, or log some data somewhere (e.g. in a file or database) which the service would detect next time its timer runs. – ADyson May 12 '19 at 21:39
  • 3
    @ADyson I don't think OP need to be concerned of "*considered* to be spyware" - it sounds like that is exactly what the goal is :) – Alexei Levenkov May 12 '19 at 22:14
  • @AlexeiLevenkov good point...I can't think of another obvious use case for such functionality right now... :) – ADyson May 13 '19 at 09:33

2 Answers2

1

As somebody has already commented, a Windows service does not have a foreground window which can receive keyboard focus or Windows keyboard messages. So your only option to achieve exactly what you're after is to use a low level event hook to receive keyboard events.

Note, however, that these are system-wide events and your service might be flooded with them. They're useful in applications like screen readers and other assistive technology, but I'd recommend trying to think about whether there is some other way to do what you want to do before using this approach. For example, can you just run an application in the system tray and subscribe to WM_HOTKEY messages via calls to RegisterHotKey?

Here's an example of a low-level keyboard hook in C#.

James Scholes
  • 7,686
  • 3
  • 19
  • 20
  • 2
    You can't use `SetWindowsHook` from service because it requires "desktop" which service does not have - https://stackoverflow.com/questions/5815424/global-keyboard-hook-from-windows-service. Please double check and edit that strange suggestion out. The second suggestion (user app to send commands to the service) is the recommended way of doing so. – Alexei Levenkov May 12 '19 at 21:21
1

The best solution I found:
Generally author creates .NET wrapper on a low-level methods from user32.dll assembly that make using those methods quite pleasant and enjoyable.

    private LowLevelKeyboardListener _listener;        
    _listener = new LowLevelKeyboardListener();
    _listener.OnKeyPressed += _listener_OnKeyPressed;
    _listener.HookKeyboard();

    void _listener_OnKeyPressed(object sender, KeyPressedArgs e)
    {
        this.textBox_DisplayKeyboardInput.Text += e.KeyPressed.ToString();
    }

here the original link

Giulio Caccin
  • 2,962
  • 6
  • 36
  • 57
צח חורי
  • 371
  • 1
  • 3
  • 9