Форум: "Основная";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];
ВнизКак получить массив символов dos-окна? Найти похожие ветки
← →
Guest32545654 (2004-03-28 16:50) [0]Здравствуйте. В режиме чистого DOS"а есть возможность получить доступ к памяти, из которой отражаются данные (символы) на экран.
Ситуация: Запускаю DOS-программу из-под Windows (98,2000). Через заданный интервал времени, нужно получить полный массив символов, который в данный момент отражается в DOS-окне.
Желательно описать способ перехвата символов окна, развернутого как на полный экран, так и не на полный.
← →
Piter © (2004-03-28 20:10) [1]Блин, ну ты и сформулировал вопрос... если я тебя правильно понял, то вот откуда-то с sources.ru:
Запуск программ с передачей консольного ввода и чтением вывода.
Компилятор: Delphi
Автор: Алексей Бойко
Это пример запуска консольных программ с передачей ей консольного ввода (как если бы он был введен с клавиатуры после запуска программы) и чтением консольного вывода. Таким способом можно запускать например стандартный виндовый ftp.exe (в невидимом окне) и тем самым отказаться от использования специализированных, зачастую глючных компонент.
function ExecuteFile(FileName,StdInput: string;
TimeOut: integer;
var StdOutput:string) : boolean;
label Error;
type
TPipeHandles = (IN_WRITE, IN_READ,
OUT_WRITE, OUT_READ,
ERR_WRITE, ERR_READ);
type
TPipeArray = array [TPipeHandles] of THandle;
var
i : integer;
ph : TPipeHandles;
sa : TSecurityAttributes;
Pipes : TPipeArray;
StartInf : TStartupInfo;
ProcInf : TProcessInformation;
Buf : array[0..1024] of byte;
TimeStart : TDateTime;
function ReadOutput : string;
var
i : integer;
s : string;
BytesRead : longint;
begin
Result := "";
repeat
Buf[0]:=26;
WriteFile(Pipes[OUT_WRITE],Buf,1,BytesRead,nil);
if ReadFile(Pipes[OUT_READ],Buf,1024,BytesRead,nil) then
begin
if BytesRead>0 then
begin
buf[BytesRead]:=0;
s := StrPas(@Buf[0]);
i := Pos(#26,s);
if i>0 then s := copy(s,1,i-1);
Result := Result + s;
end;
end;
if BytesRead1024 then break;
until false;
end;
begin
Result := false;
for ph := Low(TPipeHandles) to High(TPipeHandles) do
Pipes[ph] := INVALID_HANDLE_VALUE;
// Создаем пайпы
sa.nLength := sizeof(sa);
sa.bInheritHandle := TRUE;
sa.lpSecurityDescriptor := nil;
if not CreatePipe(Pipes[IN_READ],Pipes[IN_WRITE], @sa, 0 ) then
goto Error;
if not CreatePipe(Pipes[OUT_READ],Pipes[OUT_WRITE], @sa, 0 ) then
goto Error;
if not CreatePipe(Pipes[ERR_READ],Pipes[ERR_WRITE], @sa, 0 ) then
goto Error;
// Пишем StdIn
StrPCopy(@Buf[0],stdInput+^Z);
WriteFile(Pipes[IN_WRITE],Buf,Length(stdInput),i,nil);
// Хендл записи в StdIn надо закрыть - иначе выполняемая программа
// может не прочитать или прочитать не весь StdIn.
CloseHandle(Pipes[IN_WRITE]);
Pipes[IN_WRITE] := INVALID_HANDLE_VALUE;
FillChar(StartInf,sizeof(TStartupInfo),0);
StartInf.cb := sizeof(TStartupInfo);
StartInf.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartInf.wShowWindow := SW_SHOW; // SW_HIDE если надо запустить невидимо
StartInf.hStdInput := Pipes[IN_READ];
StartInf.hStdOutput := Pipes[OUT_WRITE];
StartInf.hStdError := Pipes[ERR_WRITE];
if not CreateProcess(nil, PChar(FileName), nil,
nil, True, NORMAL_PRIORITY_CLASS,
nil, nil, StartInf, ProcInf) then goto Error;
TimeStart := Now;
repeat
Application.ProcessMessages;
i := WaitForSingleObject(ProcInf.hProcess,100);
if i = WAIT_OBJECT_0 then break;
if (Now-TimeStart)*SecsPerDay>TimeOut then break;
until false;
if iWAIT_OBJECT_0 then goto Error;
StdOutput := ReadOutput;
for ph := Low(TPipeHandles) to High(TPipeHandles) do
if Pipes[ph]INVALID_HANDLE_VALUE then
CloseHandle(Pipes[ph]);
CloseHandle(ProcInf.hProcess);
CloseHandle(ProcInf.hThread);
Result := true;
Exit;
Error:
if ProcInf.hProcessINVALID_HANDLE_VALUE then
begin
CloseHandle(ProcInf.hThread);
i := WaitForSingleObject(ProcInf.hProcess, 1000);
CloseHandle(ProcInf.hProcess);
if iWAIT_OBJECT_0 then
begin
ProcInf.hProcess := OpenProcess(PROCESS_TERMINATE,
FALSE,
ProcInf.dwProcessId);
if ProcInf.hProcess 0 then
begin
TerminateProcess(ProcInf.hProcess, 0);
CloseHandle(ProcInf.hProcess);
end;
end;
end;
for ph := Low(TPipeHandles) to High(TPipeHandles) do
if Pipes[ph]INVALID_HANDLE_VALUE then
CloseHandle(Pipes[ph]);
end;
← →
PVOzerski © (2004-03-28 23:26) [2]А вот не могу сейчас дать ответ на вопрос :^( Однако предупреждаю: то, что изложено в [1], может и не сработать. Дело в том, что DOS-программы выводят текст на экран разными способами. Если через стандартные i/o ф-ции DOS- всё OK. А если через int 10H (если не путаю номер "видеопрерывания": давно это было) или вообще через видеопамять? Я бы лучше написал под DOS скрингрэббер, это вернее (и не так уж сложно, особенно, если не делать резидента, а вызывать из своей проги нужную через exec. Да и TSR здесь не так уж сложен). Хотя IMHO, не более того.
← →
Германн © (2004-03-29 02:14) [3]И Вы правы - PVOzerski © (28.03.04 23:26) [2]
В DOS-программах, никогда не использовал не то что DOS-прерываний, но и BIOS-прерываний. Всегда пользовался функциями ТР, пишущими прямо в ВидеоПамять.
И, кстати, TSR-программу, которая записывает экран, тут написать несложно.
← →
nikkie © (2004-03-29 02:31) [4]ReadConsoleOutputCharacter?
← →
Думкин © (2004-03-29 07:16) [5]> PVOzerski © (28.03.04 23:26) [2]
Выводили по разному, но хранились одинаково в текстовом режиме. слово на символ. адрес - $0B00:0000 кажется.
← →
PVOzerski © (2004-03-29 10:10) [6]$B800:0000 (но не у Hercules, там адрес другой, какой - не помню ...
← →
Думкин © (2004-03-29 10:22) [7]> PVOzerski © (29.03.04 10:10) [6]
Точно. Нолик глупо впереди. :-)
А графрежим у VGA - $A000:0000. А вот с SuperVGA - возиться приходилось.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.04 c