2012-05-09 20 views
1

私は別のプロセスからコンソールのバッファにアクセスするには? AttachConsole ERROR_INVALID_PARAMETER

は、DOSの16ビットアプリケーションであるReadConsoleOutputを呼び出すなど、(AttachConsoleを経由して)別のプロセスコンソールのバッファへのアクセスを取得したいです。私はパイプを使用することはできません。なぜなら、それは出力をsecuentiallyに書き出していないからです(私が何を意味するか知っていれば、FAR commanderのように "windows"をエミュレートします)。

だから私がすべき:

1)アプリ 2を起動するには)プロセスID 3を得る)AttachConsole(PROCID) 4を呼び出す)サイズ 5を取得するためにGetConsoleScreenBufferInfoを呼び出す)ReadConsoleOutput

を呼び出します問題は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; 

ドロップメモとボタン。 OnClickコールテスト(Memo1.Lines)。

===== EDIT完全なソリューション=====

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; 
+1

AttachConsole関数に 'stdcall'呼び出し規約を追加してみてください。 – RRUZ

答えて

1

定義は次のようになります。

function AttachConsole(dwProcessId: DWORD): BOOL; stdcall; external 
kernel32 name 'AttachConsole'; 

ので、コードは以下のそれは次のようになります。

if AttachConsole(ProcessId) then 

これ以上あなたを助けることはできません。

関連する問題