问题
My question is about very antique techologies. I have a task to automate old DOS software (spectrometric) that is running in Windows mode in Windows 98. I made two different solution hovewer both of them doesn't work with DOS application:
First Solution
- Making DOS Application active
- Sending input via SendInput function, like this:
void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::sendKeysViaInput(const std::vector<DWORD>& keys, int keyPause)
{
std::vector<DWORD>::const_iterator it;
INPUT keyBoardInput;
keyBoardInput.type = INPUT_KEYBOARD;
keyBoardInput.ki.wScan = 0;
keyBoardInput.ki.time = 0;
keyBoardInput.ki.dwExtraInfo = 0;
for(it = keys.begin(); it != keys.end(); it++)
{
keyBoardInput.ki.wVk = (*it);
keyBoardInput.ki.dwFlags = 0; // key down
SendInput(1, &keyBoardInput, sizeof(INPUT));
Sleep(keyPause);
keyBoardInput.ki.dwFlags = 2; // key up
SendInput(1, &keyBoardInput, sizeof(INPUT));
Sleep(keyPause);
}
}
- Generate key press via i8042 keyboard controllers: write to keyboard buffer command using D2 command, like this (KEYBOARD_CMD_REG - 0x64, KEYBOARD_DATA_REG - 0x60):
void MossbauerLab::Sm2201::SaveManager::AutoSaveManager::sendKeysViaKeyboardController(const std::vector<BYTE>& scanCodes, int keyPause)
{
std::vector<BYTE>::const_iterator it;
for(it = scanCodes.begin(); it != scanCodes.end(); it++)
{
// wait untill buffer is empty
int status = 0;
int result = 0;
do
{
status = _inp(0x64);
// std::cout <<"Keyboard status: "<< status << std::endl;
Sleep(10);
}
while (status & 1);
// send scan code for key down
_outp(KEYBOARD_CMD_REG, 0xD2);
_outp(KEYBOARD_DATA_REG, (*it));
result = _inp(KEYBOARD_DATA_REG);
std::cout <<"Keyboard command result for KEY DOWN: "<< result << std::endl;
// send scan code for key up
BYTE keyUpCode = (*it) | 128;
Sleep(keyPause);
_outp(KEYBOARD_CMD_REG, 0xD2);
_outp(KEYBOARD_DATA_REG, keyUpCode);
result = _inp(KEYBOARD_DATA_REG);
std::cout <<"Keyboard command result for KEY UP: "<< result << std::endl;
}
}
I tested both of these solutions with standard Notepad window (notepad.exe) and both of them works fine, but i can't get it work with DOS application.
My Code where i generate keyboard input (and whole project): https://github.com/MossbauerLab/Sm2201Autosave/blob/master/MossbauerLab.Sm2201.ExtSaveUtility/src/saveManager/autoSaveManager.cpp
Could you please help me to solve this solution.
回答1:
First of all i want to thank all who interesting this post, all of you gave me some useful info and i finally made what i wanted.
About how it was implemented: i've created VXD driver (it is my proprietary driver and i can't post it code here because i am planning to use it for commercial projects). But the main goal of this comment - YES, it is possible to simulate KEYBOARD INPUT for DOS application running in Windows 98 in window mode. Part of my solution that i could post is on github: https://github.com/MossbauerLab/Sm2201Autosave/blob/master/MossbauerLab.Sm2201.ExtSaveUtility/src/saveManager/autoSaveManager.cpp
Here i am using vXd accessor class: (https://github.com/MossbauerLab/Sm2201Autosave/blob/master/MossbauerLab.Sm2201.ExtSaveUtility/src/utils/windows/vxdAccessor.cpp)
Main idea - interact with driver using W32_DEVICEIOCONTROL driver message handler and DeviceIoControl function and passing struct that have 1 byte align using CTL (define in my driver) CODES: i did not used CTL_CODE macro. This Github project is almost ready ~95% (at present time i just have to manual select window to send by activate it with mouse click and check proper memory free).
回答2:
MS-DOS applications in Windows 98 run in Virtual Real Mode, not in Protected Mode, that's why it's impossible to communicate with them using protected mode drivers or system calls. You need to use BIOS / DOS interrupts to interface with keyboard, Windows drivers will not be able to do that for you.
Thus, the only way to do this, would be to simulate keypresses using another DOS application, but I am not sure whether the BIOS keyboard buffer is virtualised, but if not, then you should be able to pull it off by launching a Virtual Real Mode process from your application (will have to be a separate exe, but you should be able to get away with running it windowless) and pass over keypresses as commandline arguments to send them to BIOS.
This is a very interesting problem, hope this helps and you manage to solve it.
来源:https://stackoverflow.com/questions/59963008/how-to-send-keyboard-input-to-dos-application-running-in-window-mode-in-windows9