Я пытаюсь создать программу, которая запускается в фоновом режиме при активации горячей клавишей, она фиксирует ввод с клавиатуры и мыши, после чего вы можете воспроизвести эти вводы, если будет нажата другая горячая клавиша.
Эта концепция отлично работает в Windows, Chrome и более новых играх, даже таких, как Overwatch или Rocket League (даже если меня это не волнует). Проблема в том, что я пытаюсь захватить входные данные Call of Duty Modern Warfare (2007) и воспроизвести их, но ни захват входных данных, ни их воспроизведение не работают. Единственное, что работает, это CAPTURE движения мыши.
Я использую user32.dll для захвата и воспроизведения. Я попробовал несколько способов имитации ввода с клавиатуры, и все они работали везде, кроме этой конкретной игры.
keybd_event((byte)Key, 0, KEYEVENTF_KEYDOWN, UIntPtr.Zero);
//or
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));
Попытка имитировать ввод с клавиатуры.
Я попробовал SendInput из user32.dll, потому что я читал, что игры DirectX обрабатывают ввод по-разному, но это тоже не сработало. Реализация входных данных для SendInput
исходит из этого вопроса stackoverflow
Что касается чтения клавиатуры, я обычно использовал GetAsyncKeyState для чтения клавиатуры.
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(Keys vKey);
//....
GetAsyncKeyState(key)
GetAsyncKeyState постоянно равен 0, независимо от реальной ситуации.
Я также пробовал хуки Windows для захвата клавиатуры безрезультатно.
private static ListBox lb1;
public Form1()
{
InitializeComponent();
lb1 = listBox1;
InstallHook();
}
private const int WH_KEYBOARD_LL = 13;
// The callback function that will be called by the hook
public delegate int KeyboardHookProc(int code, int wParam, ref KeyboardHookStruct lParam);
public struct KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
// Import the SetWindowsHookEx function from the Windows API
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc lpfn, IntPtr hMod, uint dwThreadId);
// Import the UnhookWindowsHookEx function from the Windows API
[DllImport("user32.dll", SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
// Import the CallNextHookEx function from the Windows API
[DllImport("user32.dll", SetLastError = true)]
private static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, ref KeyboardHookStruct lParam);
// The hook handle
private static IntPtr hookHandle = IntPtr.Zero;
// The hook procedure
private static KeyboardHookProc hookProc = hookProcFunc;
// Install the hook
public static void InstallHook()
{
hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, IntPtr.Zero, 0);
}
// Uninstall the hook
public static void UninstallHook()
{
UnhookWindowsHookEx(hookHandle);
}
// The hook function
private static int hookProcFunc(int code, int wParam, ref KeyboardHookStruct lParam)
{
if (code >= 0)
{
// Handle the keystroke here
lb1.Items.Add("Keystroke: " + lParam.vkCode);
}
// Pass the keystroke on to the next hook in the chain
return CallNextHookEx(hookHandle, code, wParam, ref lParam);
}
mouse_event(MOUSEEVENTF_MOVE, movementX, movementY, 0, UIntPtr.Zero);
mouse_event также не имеет никакого эффекта.
Единственная часть, которая работает в этой конкретной игре, это:
[DllImport("user32.dll")]
static extern bool GetCursorPos(out Point lpPoint);
Стоит отметить, что в этой игре работают макросы AHK (AutoHotkey) и Logitech HUB. Также тот факт, что эта игра единственная, которую я заметил, где не работают ни захват, ни поднятие событий клавиатуры.
Мне понадобятся некоторые идеи, если проблема заключается в моем подходе к чтению и срабатыванию ввода с клавиатуры (и мыши) или если я неправильно понимаю, как использовать ранее упомянутые функции? Могу ли я добиться "универсального" макроса с помощью user32.dll, который будет работать с любым приложением без странностей? Если он не способен, то какие есть лучшие альтернативы, которые будут работать почти в любом случае, даже если это невозможно в С#, но, скажем, в C?
Да, я не могу запустить без прав администратора. Вы предполагаете, что моя проблема связана с привилегиями?
@NineBerry Я вручную запустил встроенный код с правами администратора, и это сработало..... ну, это интересное решение. Честно говоря, ваш вопрос как бы ответил на мой вопрос, но если бы я получил объяснение, что произошло сзади, это было бы здорово.
Windows по очевидным соображениям безопасности по умолчанию блокирует большую часть связи (сообщения Windows, доступ к дескрипторам друг друга, входные сигналы и т. д.) между процессами с повышенными и неповышенными правами.
С точки зрения процесса без повышенных прав процесс с повышенными правами выполняется как в другом сеансе Windows.
Чтобы иметь возможность взаимодействовать с процессом с повышенными правами из вашего собственного процесса, ваш собственный процесс также должен работать с повышенными правами (с правами администратора). Это включает в себя чтение и моделирование входных событий, происходящих в контексте процесса с повышенными правами.
Вы запускаете Call of Duty Modern Warfare с правами администратора?