Как отправить ввод с клавиатуры в приложение DOS, работающее в оконном режиме в Windows98 - PullRequest
3 голосов
/ 29 января 2020

Мой вопрос об очень древних технологиях. У меня есть задача автоматизировать старое программное обеспечение DOS (spectrometri c), которое работает в режиме Windows в Windows 98. Я сделал два разных решения, но оба они не работают с DOS application :

  1. Первое решение

    • Активация приложения DOS
    • Отправка ввода через функцию SendInput, например:
    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);
        }
    }
Создание нажатия клавиш с помощью контроллеров клавиатуры i8042: запись в буферную команду клавиатуры с помощью команды D2, например, (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;
        }
    }

Я тестировал оба из этих решений со стандартным окном Notepad (notepad.exe) и оба отлично работают , но я не могу заставить его работать с приложением DOS.

Мой код, где я генерирую ввод с клавиатуры (и весь проект): https://github.com/MossbauerLab/Sm2201Autosave/blob/master/MossbauerLab.Sm2201.ExtSaveUtility/src/saveManager/autoSaveManager.cpp

Не могли бы вы помочь мне решить это решение.

Ответы [ 2 ]

0 голосов
/ 02 марта 2020

Прежде всего, я хочу поблагодарить всех, кто заинтересовался этим постом, все вы дали мне некоторую полезную информацию, и я наконец сделал то, что хотел.

О том, как это было реализовано: я создал драйвер VXD (это мой проприетарный драйвер, и я не могу опубликовать его здесь, потому что планирую использовать его для коммерческих проектов). Но главная цель этого комментария - ДА, есть возможность смоделировать KEYBOARD INPUT для приложения DOS, работающего в Windows 98, в оконном режиме . Часть моего решения, которую я мог бы опубликовать, находится на github: https://github.com/MossbauerLab/Sm2201Autosave/blob/master/MossbauerLab.Sm2201.ExtSaveUtility/src/saveManager/autoSaveManager.cpp

Здесь я использую класс доступа vXd: (https://github.com/MossbauerLab/Sm2201Autosave/blob/master/MossbauerLab.Sm2201.ExtSaveUtility/src/utils/windows/vxdAccessor.cpp)

Основная идея - взаимодействовать с драйвером, используя обработчик сообщений драйвера W32_DEVICEIOCONTROL и функцию DeviceIoControl, и передавая структуру, имеющую 1 байтовое выравнивание, используя CTL (определите в моем драйвере) КОДЫ: я не использовал макрос CTL_CODE. Этот проект Github почти готов ~ 95% (в настоящее время мне просто нужно вручную выбрать окно для отправки, активировав его щелчком мыши и проверив, свободна ли память).

0 голосов
/ 10 февраля 2020

Приложения MS-DOS в Windows 98 работают в виртуальном реальном режиме, а не в защищенном режиме, поэтому с ними невозможно связаться с помощью драйверов защищенного режима или системных вызовов. Вам нужно использовать прерывания B IOS / DOS для взаимодействия с клавиатурой, драйверы Windows не смогут сделать это за вас.

Таким образом, единственный способ сделать это - симулировать нажатия клавиш. с помощью другого приложения DOS, но я не уверен, виртуализирован ли буфер клавиатуры B IOS, но если нет, то вы сможете выполнить его, запустив процесс Virtual Real Mode из своего приложения (это должно быть отдельный exe, но вы должны иметь возможность запустить его без окон) и передавать нажатия клавиш в качестве аргументов командной строки для отправки их на B IOS.

Это очень интересная проблема, надеюсь, это поможет вам удалось решить.

...