Half-Life и Adrenaline Gamer форум
http://aghl.ru/forum/

Перехват консоли HLDS на Windows
http://aghl.ru/forum/viewtopic.php?f=38&t=1996
Страница 1 из 2

Автор:  ImperNik [ 04 дек 2014, 01:58 ]
Заголовок сообщения:  Перехват консоли HLDS на Windows

Решил написать утилиту, которая позволит запустить консольный процесс с перехватом данных вывода (StdIn) и позволит отправлять команды в этот консольный процесс (StdOut). Что-то вроде аналога Screen под Linux, но только для Windows.

В качестве основы взял вот это - http://www.codenet.ru/progr/bcb/pipes.php

Получилась вполне рабочая программа, которая при тестировании перехватывала cmd и позволяла отправлять команды в запущенный процесс.

Но вот проблема. При запуске hlds создается еще один дочерний процесс, а первоначальный процесс завершается.

Сама программа:
Вложение:
screen.zip [129.67 КБ]
Скачиваний: 236


Исходник:
Вложение:
screen_source.zip [3.48 КБ]
Скачиваний: 252


Немного поясню принцип работы программы:

Запуск процесс с перехватом данных осуществляется командой:
Код:
screen.exe -t start -S hlds -c "C:\servers\hlds\hlds.exe -console -game valve +ip 127.0.0.1 +port 27015 +map crossfire"
screen.exe -t start -S hlds -c "C:\Windows\System32\cmd.exe"

Получение содержимого консоли:
Код:
screen.exe -t get_console -S hlds

Отправка в консоль:
Код:
screen.exe -t send_command -S hlds -c "changelevel stalkyard"
screen.exe -t send_command -S hlds -c "help"

Завершение:
Код:
screen.exe -t kill -S hlds

Как я написал выше, с cmd всё работает, но при запуске HLDS через эту утилиту оно будет завершено.
Хотел бы спросить у знатоков aghl. Куда мне копать чтобы получить содержимое консоли HLDS?

Автор:  Lev [ 04 дек 2014, 03:03 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

ImperNik писал(а):
screen.exe -t start -S hlds -c "C:\servers\hlds\hlds.exe -game valve +ip 127.0.0.1 +port 27015 +map crossfire"
-console параметр не добавил.

Автор:  ImperNik [ 04 дек 2014, 04:05 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

Да, это здесь не добавил. С -console также не работает.

Автор:  Lev [ 04 дек 2014, 05:50 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

Там вроде не должно быть дочернего процесса, по крайней мере с -console.
Не ковырял работу с консолью в хлдс. Если судить по описанному, то есть такие варианты:
    отловить создание процесса, перехватить ввод-вывод в нем при этом;
    хукнуть функции по работе с консолью в движке;
    скорее всего консоль там через какой-нить интерфейс реализована (чтобы можно было в GUI выводить) - можно интерфейс перехватить;

Автор:  ImperNik [ 04 дек 2014, 06:08 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

Lev писал(а):
отловить создание процесса, перехватить ввод-вывод в нем при этом;[/list]
Не представляю как это сделать.
Ведь изначально созданы пайпы (один на вывод, другой на ввод) для запускаемого процесса. Как узнать, что дочерним процессом создан еще один? Где получить дескрипторы на еще один создаваемый процесс?

Lev писал(а):
скорее всего консоль там через какой-нить интерфейс реализована (чтобы можно было в GUI выводить) - можно интерфейс перехватить;[/list]
Скорее всего так и есть. Но, опять же, как узнать, что имеем дело с GUI, и как создать пайпы на него?

Автор:  Lev [ 04 дек 2014, 06:13 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

На деле, хлдс не создает никаких дочерних процессов. Сколько в дебаге с ним просидел, никогда такого не было.
Стало быть процесс всё же один.
А тебе надо GUI хлдс хукнуть или всё же консольный? Мне почему-то кажется что консольный.
Так или иначе, если возиться с хуками - надо туда инжектиться, а в таком варианте проще уж сразу просто модуль под метамод написать.
С интрефейсами, если захотеть, можно поразбираться, получить экземпляр можно через экспортируемую функцию, а дальше надо понять как его использовать.

Автор:  ImperNik [ 04 дек 2014, 06:50 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

Хукнуть нужно именно консольный, но с HLDS это не получается.
Новый процесс запускается функцией:
Код:
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)

После запуска есть цикл, в котором имеется проверка:
Код:
GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс не закрыт
if (exit != STILL_ACTIVE)
      break;

При запуске простого консольного приложения, будь то cmd.exe или cout << "Hello, world"; sleep(2000); никаких проблем нет. Переменная exit имеет значение STILL_ACTIVE, но при запуске hlds оно имеет значение отличное от STILL_ACTIVE, если быть точнее, то 4294967295.

Проверку убрал и перехват на радость заработал. Правда при запуске через моё приложение сервер не запускается:
Код:
Console initialized.
FATAL ERROR (shutting down): W_LoadWadFile: couldn't load gfx.wad
Using breakpad crash handler
Setting breakpad minidump AppID = 70
Forcing breakpad minidump interfaces to load
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
Я так понимаю где-то нужно задать рабочую директорию.

Автор:  Lev [ 04 дек 2014, 07:00 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

Можно из одной папки запускать, можно в CreateProcess передать параметр, можно рабочую директорию сменить программно.
Насчет проверки, -1 возвращает - какая-то ошибка, скорее всего. Можешь GetLastError проверить. Или попробуй GetProcessId вместо этого.

Автор:  ImperNik [ 04 дек 2014, 07:20 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

В CreateProcess 8-ой параметр и есть директория, передал директорию и сервер запустился, порт слушает, подключиться возможно.

При запуске через screen.exe создается пустое окошко hlds. Как я понял, это из-за того, что данные уходят в другое место.
Вложение:
Windows.png
Windows.png [ 44.46 КБ | Просмотров: 4474 ]


Перехват содержимого консоли работает нормально, но вот отправка команд не работает. Не работает если отправлять через screen.exe и если вписывать в пустое окошко hlds.

Добавлено спустя 24 минуты 45 секунд:
Как я понял, проблема кроется в символах окончания строки. Когда в HLDS срабатывает отправка команды? Когда в строке есть символ \n, \r? Или как-то по другому?
Просто и то и другое испробовал, а результат нулевой.

Автор:  Lev [ 05 дек 2014, 01:56 ]
Заголовок сообщения:  Re: Перехват консоли HLDS на Windows

Команды в движок засылаются из hlds.exe через IDedicatedServerAPI интерфейс.
В hlds.exe используются GetNumberOfConsoleInputEvents и ReadConsoleInput для чтения команд в методе CTextConsoleWin32::GetLine, там же реализовано редактирование команды.
Судя по всему переопределенный stdin не влияет на ReadConsoleInput.

Можно попробовать пойти другим путем. У hlds.exe есть фича для управления вводом/выводом посредством параметров запуска -HFILE -HPARENT -HCHILD. Под это дело, в HLSDK, в utils, есть проект serverctrl. Можешь его поковырять.

Ещё можно попробовать
Код:
   FreeConsole();
   if (!AttachConsole(pi.dwProcessId))
Этот кусок кода работает, и, возможно, после этого можно будет читать/писать в консоль сервера напрямую.

Страница 1 из 2 Часовой пояс: UTC + 5 часов [ Летнее время ]
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/