|  | 
 
 | 
| 
			 
			#1  
			
			
			
			
		 | |||
| 
 | |||
|  Чтение с консоли Доброго дня. Есть программа скрин которой здесь: http://antsa.narod.ru/img.jpg Вверху есть рамочка, в рамочке значения давления, температуры, расхода, мне нужно их забрать от туда. Программа старая (вроде как) MSDOS, использует процесс который называется NTVDM.EXE, он является вирт.машиной, исполняющей 16-разрядные ДОС-приложения. Все это выводиться в консоль (CMD проще говоря). Мне позарез нужно достать от туда эти данные: Что я УЖЕ (за 3 дня) знаю что есть: ReadConsoleOutput http://winapi.freetechsecrets.com/wi...soleOutput.htm В ReadConsoleOutput функция читает характер и цвет атрибут данных из прямоугольных блоков характера клеток в буфер экрана консоли, а также функция записывает данные в прямоугольных блоков на указанном месте в буфер назначения. ReadConsoleOutputAttribute http://winapi.freetechsecrets.com/wi...tAttribute.htm В ReadConsoleOutputAttribute функция копии указанного количества плана и цвет фона атрибуты из последовательных ячеек консольный буфер экрана, начиная с указанного места. ReadConsoleOutputCharacter http://winapi.freetechsecrets.com/wi...tCharacter.htm В ReadConsoleOutputCharacter функция копии ряда персонажей из последовательных ячеек консольный буфер экрана, начиная с указанного места. Я делаю: Код: var
 pid: DWORD;
 hStdout: thandle;
 Buffer:array of integer;
 c:coord;
 wr:cardinal;
begin
 c.X:=1;
 c.Y:=1;
 GetWindowThreadProcessId(FindWindow('C:\WINDOWS\system32\cmd.exe',nil), @pid);
 hStdout := GetStdHandle(STD_OUTPUT_HANDLE);
 ReadConsoleOutputAttribute(hStdout,@Buffer[0],2,C,Wr);
 Memo1.Lines.Add(IntToStr(buffer[0]));
 Memo1.Lines.Add(IntToStr(wr));
end; | 
| 
			 
			#2  
			
			
			
			
		 | ||||
| 
 | ||||
|   Не пользовался такими функциями, но могу предположить, что чтение аттрибута вам ненужно, если там консоль интерпретируется как экран 80х25, то имеем 4000 байт, где 2000 байт аттрибут цвета (нафик вам ненужные) и 2000 байт собственно знаки. Потому скорее всего надо использовать ReadConsoleOutputCharacter. Могу так-же предположить, что вместо Buffer:array of integer; надо сделать Buffer:array[1..2000] of byte; Тогда по логиге из Buffer вас будет интересовать 2 и 3 строка т.е. 81-240 символы. | 
| 
			 
			#3  
			
			
			
			
		 | |||
| 
 | |||
|   Цитата: 
 | 
| 
			 
			#4  
			
			
			
			
		 | ||||
| 
 | ||||
|   Можно и так конечно, хотя большой разницы нет, что 14 раз вызвать функцию с нужными координами, что прочитать один раз 160 байт и обращаться к нужному элементу по индексу. | 
| 
			 
			#5  
			
			
			
			
		 | |||
| 
 | |||
|   Только вопрос как получить это??!?!?!? | 
| 
			 
			#6  
			
			
			
			
		 | ||||
| 
 | ||||
|   У меня появилось сильное сомнение, что Код: hStdout := GetStdHandle(STD_OUTPUT_HANDLE) | 
| 
			 
			#7  
			
			
			
			
		 | |||
| 
 | |||
|   Цитата: 
 | 
| 
			 
			#8  
			
			
			
			
		 | ||||
| 
 | ||||
|   Я ведь тоже неиспользовал ранее этих функций, так-что тоже пионер в данном вопросе, но может у вас и правильно, а у меня он возвращает 0 и в Buffer у меня ничего невозвращается. | 
| 
			 
			#9  
			
			
			
			
		 | ||||
| 
 | ||||
|   Можно использовать AttachConsole, но эта функция есть только в Windows XP и выше. Вот готовая программа на WinAPI, котороя ловит окно по его названию и создает текстовый файл с содержимым этого окна. Код: program uAttachConsole;
uses                   
  Windows;
const
   _WIN32_WINNT = $0501;
type
   TAttachConsole = function (dwProcessId: DWORD): LongBOOL stdcall;
var
  AttachConsole: TAttachConsole;
  mProcessID, Wnd, Hcwnd, chRead: Cardinal;
  BufInfo: _CONSOLE_SCREEN_BUFFER_INFO;
  lpCh: PChar;
  Coord: _COORD;
  i: Integer;
function FileExists(const FileName: string): Boolean;
var
  FindData: TWin32FindData;
  F: THandle;
begin
  F:= FindFirstFile(PChar(FileName), FindData);
  Result:= (F <> INVALID_HANDLE_VALUE);
  if Result then FindClose(F);
end;
function ChangeFileExt(const FName, newExt: string): string;
var
  i, x, e: integer;
begin
  e:= Length(FName); x:= e;
  for i:= e downto 1 do
    if FName[i] = '.' then
    begin
      x:= i - 1;
      break;
    end;
  Result:= Copy(FName, 1, x) + newExt;
end;
function OpenFile(var fLog: TextFile; const LogFileName: String;
   const IsErase: Boolean = False): Boolean;
{var
   TmpStr: String; }
begin
{$I-}
   AssignFile(fLog, LogFileName);
   Result := IOResult = 0;
   if Result then begin
      if IsErase or (not FileExists (LogFileName)) then
         Rewrite(fLog)
      else
         Append(fLog);
      Result := IOResult = 0;
   end;
{$I+}
end;
function WriteLnStr(var fLog: TextFile; const fStr: string): boolean;
begin
{$I-}
   Writeln (fLog, fStr);
   Result := IOResult = 0;
   if Result then begin
      Flush (fLog);
      Result := IOResult = 0;
   end;
{$I+}
end;
procedure CloseFile(var fLog: TextFile);
begin
{$I-}
  Flush(fLog);
  System.CloseFile(fLog);
{$I+}
end;
function StrFile(const fStr, fFileName: String;
   const IsErase: Boolean = False): Boolean;
var
   fLog: TextFile;
begin
   Result := OpenFile(fLog, fFileName, IsErase);
   if Result then begin
      try
         Result := WriteLnStr(fLog, fStr);
      finally
         CloseFile(fLog);
      end;
   end;
end;
begin
  @AttachConsole:= GetProcAddress(GetModuleHandle('kernel32.dll'), 'AttachConsole');
  if @AttachConsole = nil then
  begin
    MessageBox(0, 'Программа работает только под Windows XP и выше!', 'Error', 16);
    Halt(1);
  end;
//  Wnd:= FindWindow(nil, 'Командная строка');
  Wnd:= FindWindow(nil, 'C:\WINDOWS\system32\cmd.exe');
  GetWindowThreadProcessId(Wnd, @mProcessID);
  if AttachConsole(mProcessID) then begin
    Hcwnd:= GetStdHandle(STD_OUTPUT_HANDLE);
    GetConsoleScreenBufferInfo(Hcwnd, BufInfo);
    GetMem(lpCh, BufInfo.dwMaximumWindowSize.X+1);
    try
      for i:=0 to BufInfo.dwSize.Y-1 do begin
         Coord.X := 0;
         Coord.Y := i;
         ReadConsoleOutputCharacter(Hcwnd, lpCh, BufInfo.dwMaximumWindowSize.X, Coord, chRead);
         StrFile(lpCh, ChangeFileExt(ParamStr(0), '.log'), False);
      end;
    finally
      FreeMem(lpCh, BufInfo.dwMaximumWindowSize.X+1);
    end;
  end;
  Halt(0);
end. | 
| 
			 
			#10  
			
			
			
			
		 | |||
| 
 | |||
|   Цитата: 
 Да!!! Лед тронулся: Код: procedure TForm1.Button9Click(Sender: TObject);
type
   TAttachConsole = function (dwProcessId: DWORD): LongBOOL stdcall;
var
  AttachConsole: TAttachConsole;
  mProcessID, Hcwnd, chRead: Cardinal;
  BufInfo: _CONSOLE_SCREEN_BUFFER_INFO;
  lpCh : PChar;
  Coord: _COORD;
  i: Integer;
  Phwnd:HWND;
  ii:bool;
begin
  Phwnd:=FindWindow(nil,'C:\WINDOWS\system32\cmd.exe');
  @AttachConsole := GetProcAddress(GetModuleHandle('kernel32.dll'), 'AttachConsole');
  GetWindowThreadProcessId(Phwnd,@mProcessID);
  if AttachConsole(mProcessID) then begin
    Hcwnd:=GetStdHandle(STD_OUTPUT_HANDLE);
    GetConsoleScreenBufferInfo (Hcwnd, BufInfo);
    GetMem(lpCh, BufInfo.dwMaximumWindowSize.Y*BufInfo.dwMaximumWindowSize.X);
    Coord.X:=0;
    Coord.Y:=0;
   ii := ReadConsoleOutputCharacter(Hcwnd,lpCh,BufInfo.dwMaximumWindowSize.X,Coord,chRead);
    If ii then Memo1.Lines.Add('yes'); //успешон забрали с консоли
    If not ii then Memo1.Lines.Add('no'); //не забрали с консоли
     Memo1.Lines.Add(lpCh);  //выводим то что забрали
        Memo1.Lines.Add('Phwnd '+IntToStr(Phwnd));
        Memo1.Lines.Add('Hcwnd '+IntToStr(Hcwnd));
  end else Memo1.Lines.Add('Nea');
end; | 
| 
			 
			#11  
			
			
			
			
		 | |||
| 
 | |||
|   Цитата: 
 Это было то, что нужно пошарив про функцию аттачконсоль, я нашел много интересного и написал: Код: type
 TAttachConsole = function (dwProcessId: DWORD): LongBOOL stdcall;
var
 AttachConsole: TAttachConsole;
 mProcessID, Hcwnd: Cardinal;
procedure TForm1.FormCreate(Sender: TObject);
begin
 @AttachConsole := GetProcAddress(GetModuleHandle('kernel32.dll'), 'AttachConsole');
 GetWindowThreadProcessId(FindWindow(nil,'C:\WINDOWS\system32\cmd.exe'),@mProcess ID);
 AttachConsole(mProcessID);
end;
function TForm1.ReadCMD(x, y: byte): string;
const
 SMB = 4;
var
 chRead: Cardinal;
 BufInfo: _CONSOLE_SCREEN_BUFFER_INFO;
 lpCh : PChar;
 Coord: _COORD;
begin
   Hcwnd:=GetStdHandle(STD_OUTPUT_HANDLE);
   GetConsoleScreenBufferInfo (Hcwnd, BufInfo);
   GetMem(lpCh,SMB);
   Coord.X:=x;
   Coord.Y:=y;
   ReadConsoleOutputCharacter(Hcwnd,lpCh,SMB,Coord,chRead);
   Result:=copy(lpCh,1,SMB);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
 Memo1.Lines.Add(ReadCMD(22,1));
end;Спасибо огромное!!! |