我想访问另一个进程控制台的缓冲区(通过AttachConsole),调用ReadConsoleOutput等
是一个DOS 16位应用程序。 我不能使用pipe道,因为它不会写输出secuentially(它模拟“窗口”..如FAR指挥官,如果你知道我的意思)。
所以我应该:
1)启动应用程序2)获取进程ID 3)调用AttachConsole(ProcId)4)调用GetConsoleScreenBufferInfo获取大小5)调用ReadConsoleOutput
在Windows上,控制台窗口所有权如何工作?
在Linux中使用Ctrl-Alt-F6,无法恢复屏幕
如何将Alt +空格发送到控制台窗口?
在程序运行的时候可以获得程序的输出吗?
问题是在3:当我调用AttachConsole ir时返回0,在调用GetLastError之后,它报告ERROR_INVALID_ParaMETER 87(0x57)。
AttachConsole的唯一参数是ProcessId,我用ProcessExplorer检查了它是正确的(它实际上是模拟应用程序的ntvdm.exe的PID)。
Delphi代码:
function AttachConsole(dwProcessId: DWORD): Cardinal; external kernel32 name 'AttachConsole'; var Handle: HWND; function EnumWindowsProc(hwnd: HWND; lParam: LParaM): BOOL; stdcall; var s: string; IsVisible,IsOwned,IsAppWindow: Boolean; begin Result := True;//carry on enumerating IsVisible := IsWindowVisible(hwnd); if not IsVisible then exit; IsOwned := Getwindow(hwnd,GW_OWNER)<>0; if IsOwned then exit; IsAppWindow := getwindowlongPtr(hwnd,GWL_STYLE) and WS_EX_APPWINDOW<>0; if not IsAppWindow then exit; SetLength(s,GetwindowTextLength(hwnd)); GetwindowText(hwnd,PChar(s),Length(s)+1); if AnsiContainsText(s,'????.EXE') then // set windows name to search Handle := hwnd; end; procedure Test(Strings: TStrings); var ProcessID: Cardinal; begin Handle := 0; EnumWindows(@EnumWindowsProc,0); Strings.Add('Handle: ' + IntToStr(Handle)); if Handle <> 0 then SetForegroundWindow(Handle); Sleep(100); GetwindowThreadProcessId(Handle,@ProcessID); Strings.Add('ProcessId: ' + IntToStr(ProcessID)); if AttachConsole(ProcessId) <> 0 then Strings.Add('Ok Attached') else Strings.Add('Error: ' + IntToStr(GetLastError)); end;
放下备忘录和button的forms。 在OnClick调用Test(Memo1.Lines)。
=====编辑完整的解决scheme=====
function AttachAndGetConsoleHandle(ProcessId: Cardinal): Cardinal; begin if not AttachConsole(ProcessId) then raise Exception.Create('AttachConsole error: ' + IntToStr(GetLastError)); Result := GetStdHandle(STD_OUTPUT_HANDLE); if Result = INVALID_HANDLE_VALUE then raise Exception.Create('GetStdHandle(STD_OUTPUT_HANDLE) error: ' + IntToStr(GetLastError)); end; procedure DettachConsole; begin if not FreeConsole then raise Exception.Create('FreeConsole error: ' + IntToStr(GetLastError)); end; function ReadConsole(ConsoleHandle: Cardinal): TStringList; var BufferInfo: _CONSOLE_SCREEN_BUFFER_INFO; BufferSize,BufferCoord: _COORD; ReadRegion: _SMALL_RECT; Buffer: Array of _CHAR_INFO; I,J: Integer; Line: AnsiString; begin Result := TStringList.Create; ZeroMemory(@BufferInfo,SizeOf(BufferInfo)); if not GetConsoleScreenBufferInfo(ConsoleHandle,BufferInfo) then raise Exception.Create('GetConsoleScreenBufferInfo error: ' + IntToStr(GetLastError)); SetLength(Buffer,BufferInfo.dwSize.X * BufferInfo.dwSize.Y); BufferSize.X := BufferInfo.dwSize.X; BufferSize.Y := BufferInfo.dwSize.Y; BufferCoord.X := 0; BufferCoord.Y := 0; ReadRegion.Left := 0; ReadRegion.Top := 0; ReadRegion.Right := BufferInfo.dwSize.X; ReadRegion.Bottom := BufferInfo.dwSize.Y; if ReadConsoleOutput(ConsoleHandle,Pointer(Buffer),BufferSize,BufferCoord,ReadRegion) then begin for I := 0 to BufferInfo.dwSize.Y - 1 do begin Line := ''; for J := 0 to BufferInfo.dwSize.X - 1 do Line := Line + Buffer[I * BufferInfo.dwSize.X + J].AsciiChar; Result.Add(Line) end end else raise Exception.Create('ReadConsoleOutput error: ' + IntToStr(GetLastError)); end;
我怎样才能使Unicode iostream I / O在Windows和Unix的土地上工作?
控制台中的铃声挂起Windows 7
我怎样才能在c ++控制台中写入文本而不会破坏行
定义应该是:
function AttachConsole(dwProcessId: DWORD): BOOL; stdcall; external kernel32 name 'AttachConsole';
所以它后面的代码应该是:
if AttachConsole(ProcessId) then
再也不能帮你了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。