2

I want to make an application that will exit out of Microsoft Edge or Google Chrome whenever I type in "porn" in the interval of 10 seconds. This works fine when I have my application show the form, but I want it to be able to recognize the keys while my application is not focused.

Here is all of my code:

public partial class Form1 : Form
{


    private NotifyIcon icon;
    private int counter;
    private Timer timer;

    public Form1()
    {
        InitializeComponent();


        this.Visible = false;
        this.WindowState = FormWindowState.Minimized;
        this.ShowInTaskbar = false;


        counter = 0;

        string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

        Icon pornIcon = new Icon(path + "/pornquitter.ico");

        icon = new NotifyIcon();
        icon.BalloonTipTitle = "Porn Quitter v0.1";
        icon.Icon = pornIcon;
        icon.Visible = true;

        MenuItem item1 = new MenuItem();
        item1.Text = "Porn Quitter v0.1";
        MenuItem item2 = new MenuItem();
        item2.Text = "Quit !";

        ContextMenu menu = new ContextMenu();
        menu.MenuItems.Add(item1);
        menu.MenuItems.Add(item2);

        icon.ContextMenu = menu;

        item2.Click += Item2_Click;


        timer = new Timer();
        timer.Interval = 10000;
        timer.Start();

        timer.Tick += Timer_Tick;

    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        counter = 0;
    }

    private void Item2_Click(object sender, EventArgs e)
    {
        icon.Dispose();
        timer.Stop();
        this.Close();

    }
    private void Form1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if(counter < 4)
        {
            if (e.KeyChar.ToString().ToLower().ToCharArray(0,1)[0] == 'p' && counter == 0) counter++;
            else if (e.KeyChar.ToString().ToLower().ToCharArray(0, 1)[0] == 'o' && counter == 1) counter++;
            else if (e.KeyChar.ToString().ToLower().ToCharArray(0, 1)[0] == 'r' && counter == 2) counter++;
            else if (e.KeyChar.ToString().ToLower().ToCharArray(0, 1)[0] == 'n' && counter == 3) counter++;
            else counter = 0;
        }
        if(counter == 4)
        {
            Process[] chromeInstances = Process.GetProcessesByName("chrome");
            Process[] edgeInstances = Process.GetProcessesByName("MicrosoftEdge");
            if (chromeInstances.Length > 0)
            {
                //then chrome is up
                foreach (var p in chromeInstances)
                {
                    p.Kill();
                }
            }
            if(edgeInstances.Length > 0)
            {
                foreach(var p in edgeInstances)
                {
                    p.Kill();
                }
            }    
            counter = 0;
        }
    }
Gigaxel
  • 1,058
  • 1
  • 9
  • 20

1 Answers1

0

To intercept key presses while the application is not in focus, you can use SetWindowsHookEx:

// Declarations

private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;

private delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, IntPtr lParam); // MISSING

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
    LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
    IntPtr wParam, IntPtr lParam);

private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
            GetModuleHandle(curModule.ModuleName), 0);
    }
}

Then in your program call SetHook:

_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);

You also need to declare a HookCallBack, which is where you can handle the keypresses:

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);
        var keyName = Enum.GetName(typeof(Keys), vkCode);

        // Handle the key press here
        Console.WriteLine((Keys)vkCode);
    }

    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

The code above will just write the key pressed to the console whether or not you have the application in focus. You should be able to work out the rest of the logic from there.

Check out PInvoke for more details, and MSDN for an example which I found useful when implementing this.

Bassie
  • 9,529
  • 8
  • 68
  • 159