program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, WinUtils;
function IsWinNT : boolean;
var
osv : OSVERSIONINFO;
begin
FillChar(osv, SizeOf(osv), 0);
osv.dwOSVersionInfoSize := sizeof(osv);
GetVersionEx(osv);
result := (osv.dwPlatformId = VER_PLATFORM_WIN32_NT);
end;
var
newstdin, newstdout, read_stdout, write_stdin : THandle;
tmpStdIn, tmpStdOut, tmpStdErr : THandle;
si : STARTUPINFO;
sa : SECURITY_ATTRIBUTES;
sd : SECURITY_DESCRIPTOR;
pi : PROCESS_INFORMATION;
ph, tmp : THandle;
exe : string;
exit, bread, avail : cardinal;
buf : array [0 .. 1023] of char;
str : string;
code : cardinal;
begin
tmpStdIn:=GetStdHandle(STD_INPUT_HANDLE);
tmpStdOut:=GetStdHandle(STD_OUTPUT_HANDLE);
tmpStdErr:=GetStdHandle(STD_ERROR_HANDLE);
if IsWinNT then
begin
InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@sd, true, nil, false);
sa.lpSecurityDescriptor := @sd;
end
else sa.lpSecurityDescriptor := nil;
sa.nLength := sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle := true;
CreatePipe(newstdin, write_stdin, @sa, 0);
CreatePipe(read_stdout, newstdout, @sa, 0);
tmp := INVALID_HANDLE_VALUE;
Ph:=GetCurrentProcess;
DuplicateHandle(Ph, write_stdin, Ph, @tmp, 0, false, DUPLICATE_SAME_ACCESS);
CloseHandle(write_stdin);
write_stdin:=tmp;
tmp := INVALID_HANDLE_VALUE;
Ph:=GetCurrentProcess;
DuplicateHandle(Ph, read_stdout, Ph, @tmp, 0, false, DUPLICATE_SAME_ACCESS);
CloseHandle(read_stdout);
read_stdout:=tmp;
FillChar(si, SizeOf(si), 0);
si.cb := SizeOf(si);
GetStartupInfo(si);
si.hStdOutput := GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError := GetStdHandle(STD_ERROR_HANDLE);
si.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
si.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
si.wShowWindow := 1;
si.hStdOutput := newstdout;
si.hStdError := newstdout;
si.hStdInput := newstdin;
si.lpTitle := Pointer(exe);
exe := 'c:\windows\system32\cmd.exe';
// tmpStdIn:=GetStdHandle(STD_INPUT_HANDLE);
// SetStdHandle(STD_INPUT_HANDLE, si.hStdInput);
// tmpStdOut:=GetStdHandle(STD_OUTPUT_HANDLE);
// SetStdHandle(STD_OUTPUT_HANDLE, si.hStdOutput);
// tmpStdErr:=GetStdHandle(STD_ERROR_HANDLE);
// SetStdHandle(STD_ERROR_HANDLE, si.hStdError);
if not CreateProcess(PChar(exe), nil, nil, nil, true, CREATE_NEW_CONSOLE, nil, nil, si, pi) then
begin
code := GetLastError;
end
else
begin
// SetStdHandle(STD_INPUT_HANDLE, tmpStdIn);
// SetStdHandle(STD_OUTPUT_HANDLE, tmpStdOut);
// SetStdHandle(STD_ERROR_HANDLE, tmpStdErr);
sleep(100);
while true do
begin
GetExitCodeProcess(pi.hProcess, exit);
if (exit <> STILL_ACTIVE) then break;
PeekNamedPipe(read_stdout, @buf, 1024, @bread, @avail, nil);
while (bread <> 0) do
begin
fillChar(buf, 1024, 0);
ReadFile(read_stdout, buf, 1024, bread, nil);
SetString(str, PChar(String(@Buf)), bread);
WriteFile(tmpStdOut, Pointer(str)^, length(str), bread, nil);
//write(str);
PeekNamedPipe(read_stdout, @buf, 1024, @bread, @avail, nil);
end;
fillChar(buf, 1024, 0);
// readln(str);
ReadFile(tmpStdIn, buf, 1024, bread, nil);
SetString(str, PChar(String(@Buf)), bread);
WriteFile(write_stdin, Pointer(str)^, bread, bread, nil);
// ReadFile(read_stdout, buf, 1024, bread, nil);
sleep(100);
if str = 'exit' then break;
end;
TerminateProcess(pi.hProcess, 0);
end;
end.
Проблема с чтением и выводом Pipe. Помогите разобраться.
Код:
Работает почему то неверно. Запсукаю приложение:
Код:
Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.
W:\Prg\Delphi\Projects\ResourceMaker\2>fg
fg
"fg" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
W:\Prg\Delphi\Projects\ResourceMaker\2>fff
fff
"fff" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
W:\Prg\Delphi\Projects\ResourceMaker\2>
(С) Корпорация Майкрософт, 1985-2001.
W:\Prg\Delphi\Projects\ResourceMaker\2>fg
fg
"fg" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
W:\Prg\Delphi\Projects\ResourceMaker\2>fff
fff
"fff" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
W:\Prg\Delphi\Projects\ResourceMaker\2>
почему строчки "fff" и "fg" повторяються 2 раза. В командной строке мы такого не наблюдаем.
Если в коде
Код:
fillChar(buf, 1024, 0);
// readln(str);
ReadFile(tmpStdIn, buf, 1024, bread, nil);
SetString(str, PChar(String(@Buf)), bread);
WriteFile(write_stdin, Pointer(str)^, bread, bread, nil);
// ReadFile(read_stdout, buf, 1024, bread, nil);
sleep(100);
if str = 'exit' then break;
// readln(str);
ReadFile(tmpStdIn, buf, 1024, bread, nil);
SetString(str, PChar(String(@Buf)), bread);
WriteFile(write_stdin, Pointer(str)^, bread, bread, nil);
// ReadFile(read_stdout, buf, 1024, bread, nil);
sleep(100);
if str = 'exit' then break;
раскоментировать ReadFile(read_stdout, buf, 1024, bread, nil); то все становиться норм. Но это не выход. А что если он прочитает, не тот символ, к-й мы отправили, а уже ответ, как мы узнаем об этом?