Windows平台下用C#实现游戏Farming Bot按键监听与控制方案咨询
Windows下C#实现事件驱动的Farming Bot方案
核心思路
要实现全局监听F1/ESC按键(游戏运行时控制台可能处于后台),结合事件驱动逻辑控制自动按键的启停,需通过Windows全局键盘钩子实现按键监听,再配合自定义事件触发Bot的启动/停止逻辑。
1. 封装Windows API(含已有的按键模拟)
先封装必要的User32.dll函数,包括全局钩子相关方法和按键模拟:
using System; using System.Runtime.InteropServices; using System.Threading; public static class User32 { public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); public const int WH_KEYBOARD_LL = 13; public const int WM_KEYDOWN = 0x0100; public const int VK_F1 = 0x70; public const int VK_ESCAPE = 0x1B; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr GetModuleHandle(string lpModuleName); // 按键模拟实现(统一封装已有逻辑) [DllImport("user32.dll", SetLastError = true)] public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); public const uint KEYEVENTF_KEYDOWN = 0x0000; public const uint KEYEVENTF_KEYUP = 0x0002; public static void PressKey(byte keyCode) { keybd_event(keyCode, 0, KEYEVENTF_KEYDOWN, UIntPtr.Zero); Thread.Sleep(50); // 模拟按键按下延迟,可调整 keybd_event(keyCode, 0, KEYEVENTF_KEYUP, UIntPtr.Zero); Thread.Sleep(50); } }
2. 全局键盘钩子(事件驱动监听)
实现全局钩子管理器,当F1/ESC按下时触发自定义事件:
public class GlobalKeyboardHook : IDisposable { private User32.LowLevelKeyboardProc _hookCallback; private IntPtr _hookId = IntPtr.Zero; // 自定义事件,供外部订阅 public event EventHandler StartBotRequested; public event EventHandler StopBotRequested; public GlobalKeyboardHook() { _hookCallback = HookProc; _hookId = SetupHook(); } private IntPtr SetupHook() { using (var currentProcess = System.Diagnostics.Process.GetCurrentProcess()) using (var mainModule = currentProcess.MainModule) { return User32.SetWindowsHookEx(User32.WH_KEYBOARD_LL, _hookCallback, User32.GetModuleHandle(mainModule.ModuleName), 0); } } private IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam) { // 仅处理按键按下事件 if (nCode >= 0 && wParam == (IntPtr)User32.WM_KEYDOWN) { var keyCode = Marshal.ReadInt32(lParam); switch (keyCode) { case User32.VK_F1: StartBotRequested?.Invoke(this, EventArgs.Empty); break; case User32.VK_ESCAPE: StopBotRequested?.Invoke(this, EventArgs.Empty); break; } } // 传递钩子给下一个处理程序,避免影响系统其他按键 return User32.CallNextHookEx(_hookId, nCode, wParam, lParam); } public void Dispose() { User32.UnhookWindowsHookEx(_hookId); } }
3. Farming Bot逻辑(事件驱动控制)
实现Bot类,通过Start/Stop方法控制自动按键循环,用volatile保证线程安全:
public class FarmingBot { private volatile bool _isRunning; private Thread _botThread; public void Start() { if (_isRunning) return; _isRunning = true; _botThread = new Thread(RunAutoPressLoop) { IsBackground = true }; _botThread.Start(); } public void Stop() { _isRunning = false; _botThread?.Join(); } private void RunAutoPressLoop() { while (_isRunning) { // 循环按下A、B、C User32.PressKey(0x41); // A键 User32.PressKey(0x42); // B键 User32.PressKey(0x43); // C键 Thread.Sleep(1000); // 循环间隔,根据游戏需求调整 } } }
4. 整合到控制台程序
在Main方法中初始化钩子和Bot,订阅事件并保持程序运行:
class Program { static void Main(string[] args) { using var hook = new GlobalKeyboardHook(); var bot = new FarmingBot(); hook.StartBotRequested += (_, __) => { Console.WriteLine("Bot已启动(F1按下)"); bot.Start(); }; hook.StopBotRequested += (_, __) => { Console.WriteLine("Bot已停止(ESC按下)"); bot.Stop(); }; Console.WriteLine("按F1启动Bot,ESC停止Bot,按任意键退出程序..."); Console.ReadKey(); bot.Stop(); } }
5. 整合到.NET Core Worker Service
如果用Worker Service,在Worker类中初始化资源并处理生命周期:
public class Worker : BackgroundService { private GlobalKeyboardHook _keyboardHook; private FarmingBot _farmingBot; protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _keyboardHook = new GlobalKeyboardHook(); _farmingBot = new FarmingBot(); // 订阅钩子事件 _keyboardHook.StartBotRequested += (_, __) => _farmingBot.Start(); _keyboardHook.StopBotRequested += (_, __) => _farmingBot.Stop(); // 程序停止时清理资源 stoppingToken.Register(() => { _keyboardHook.Dispose(); _farmingBot.Stop(); }); await Task.Delay(Timeout.Infinite, stoppingToken); } }
注意事项
- 建议以管理员身份运行程序,避免全局钩子被系统或游戏拦截。
- 按键延迟和循环间隔需根据游戏的输入响应速度调整,确保按键被正确识别。
- 全局钩子会监听系统所有按键,需确保钩子回调逻辑简洁,避免影响系统性能。
内容的提问来源于stack exchange,提问作者Benjamin Martin
相关产品推荐
相关产品推荐

