0

I was always intrigued on how TSR programs worked so I decided to begin creating an extremely primitive one.

This C program reads keyboard keystrokes and prints them on console screen unless you type a then b then c then a message box will tell you that you typed abc and exits also q will cause the program to quit.

Some notes, the program is taking a least 15% of my CPU in task manager, why? I tried comparing the keystroke to 27 as in ESC but it didn't work.

#include <stdio.h>
#include <conio.h>
#include <Windows.h>

int main() {
  char i;

  while (1) {
    if (kbhit()) {
      i = getch();
      if (i == 'q')
        return 0;
      if (i == 'a') {
        i = getch();
        if (i == 'b') {
          i = getch();
          if (i == 'c') {
            int ans = MessageBox(NULL, "You typed abc\nPress OK to exit", "TSR confirmation", MB_ICONINFORMATION | MB_OK);
            if (ans == 1)
              return 0;
          }
        }
      }
      printf("You pressed %c\n", i);
    }
  }
  return 0;
}

My questions: The console still shows, I tried to compile it as a Windows program, it loaded itself in memory and I lost it without the console and had to use Task Manager to kill it, is there a way to make it resident in memory and always monitor my keystrokes for the sequence without the console.

Is there a better way to listen to a longer sequence of characters without nested ifs, it becomes ugly with longer sequences.

user10191234
  • 531
  • 1
  • 4
  • 24
  • On Windows (and other multitasking operating systems) each process has its own input queue. You'll need to use a keyboard hook to monitor input that occurs when your program does not have focus. – 500 - Internal Server Error Jan 08 '21 at 11:49
  • TSR is a MS-DOS thing, the concept makes little sense in Windows. It's how to make a background task in a single-tasking system. If no key is pressed, your loop is basically a `while (1) {}` which eats CPU. What are you trying to achieve anyway? –  Jan 08 '21 at 11:53
  • Just trying to understand how a process can still monitor what is happening even when present in the background. – user10191234 Jan 08 '21 at 12:00
  • The DOS answer to that was to install an interrupt handler. Windows won't let you do that. –  Jan 08 '21 at 12:03
  • The Win32 API has calls to install callbacks on several events, and so also on key events. Please visit the MSDN and start reading. @dratenik This way a key logger is really quite simple. Done that, with AutoIt3. – the busybee Jan 08 '21 at 13:10

1 Answers1

2

Why is the program taking a least 15% of my CPU in task manager?

Because your program restlessly executes the loop. And it seems that you have a CPU with 6 or 8 (virtual) cores. Actually your program takes about 100% of one core.

You can reduce this "load" a lot by inserting a Sleep(1) in the loop. This inserts a "sleeping" phase, which is so much longer than the runtime of a single turn of the loop, that the load will drop to nearly 0%.

Is there a way to make it resident in memory and always monitor my keystrokes for the sequence without the console?

As Windows is a multitasking system, each process that is not stopped is a resident process. You can simply program an endless loop, as you already did.

To monitor all keystrokes, you can try to use a so-called callback function, which is called for each keyboard event. Start at the MSDN page about SetWindowsHookEx() to learn more. Note, this is not a beginner's task.

Is there a better way to listen to a longer sequence of characters without nested ifs?

Sure, use a finite state machine. Since an explanation will take much more room than appropriate, please learn about this yourself. You might start at the Wikipedia page on the matter.

the busybee
  • 10,755
  • 3
  • 13
  • 30