Текущий архив: 2006.07.16;
Скачать: CL | DM;
ВнизЗапуск программ с передачей консольного ввода и чтением вывода Найти похожие ветки
← →
DmitriyR (2006-06-19 12:04) [0]Есть старая прога проблеммы в том что она консольная, есть сайт с исходником http://www.sources.ru/delphi/system/delphi_pipes.shtml
сильно не пинайте я не профи я токо учусь :)
Никак не могу заставить работать етот код.
Мне надо из своей проги написаной на Делфи запустить ету старую консольную прогу и получать от нее текст и передавать ей текст (тоесть как будто ето какаято функция в моей проге).
Знающие люди помогите разобратся.
← →
Сергей М. © (2006-06-19 12:47) [1]
> Никак не могу заставить работать етот код
Расскажи как ты пытался "заставить" ..
← →
DmitriyR (2006-06-19 12:55) [2]Может я что делаю неправильно но делаю так:
Копирую код что дан на ссылке и вставляю его в свою программу.
Далее пытаюсь вызвать ету самую функцию.
при компиляции вываливает пару десятков ошибок типа:
Types of actual and format var parameters must be identical
на строку:
WriteFile(Pipes[IN_WRITE], Buf, Length(stdInput), i, nil);
конкретно на i: integer которая задана ранее, если я делаю i: cardinal
то ошибка исчезает, но их еще море других :(
ето я туплю или код выложен с таким приколом.
Еще раз сильно не пинайте я новичек :)
Помогите разобратся в чем беда?
← →
tesseract © (2006-06-19 13:18) [3]
> Types of actual and format var parameters must be identical
Смотри внимательнее описание функции. Не те данные передаёшь.
← →
Сергей М. © (2006-06-19 13:22) [4]Сравнивай этот исправленный код с ориг.кодом и разбирайся, какие ошибки в последнем присутствовали:
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 : Cardinal;
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 : Cardinal;
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 BytesRead = 1024 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 i <> WAIT_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.hProcess <> INVALID_HANDLE_VALUE then
begin
CloseHandle(ProcInf.hThread);
i := WaitForSingleObject(ProcInf.hProcess, 1000);
CloseHandle(ProcInf.hProcess);
if i = WAIT_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;
← →
DmitriyR (2006-06-19 13:37) [5]Вот ето веселье :(
В инете везде полно етого кода и везде он с одними и темиже ошибками :(
я уже тоже переделал интегер на кардинал но вот твой код дал конечный результат в простановке знаков в командах if (<>,= и т.д.)
их почти нигде нет :(
щас попробую твой код надеюсь все пойдет :)
Похоже все просто перепечатывают 1 страничку не смотря что код не рабочий :(
Хоть бы дописали тогда:
П.С. Доработать напильником :)
Спасибо за помощь, щас попробую.
Да вот еще сразу мож подскажеш как правильно вызывать ету функцию?
я делаю так:
на форме лежит Edit в него набираю (c:\winnt\system32\cmd.exe)
далее на форме Button при нажатии вызывает:
ExecuteFile(Edit.Text, "что надо тут", 1000,"что надо тут");
Заранее спасибо.
← →
Сергей М. © (2006-06-19 14:46) [6]
> инете везде полно етого кода и везде он с одними и темиже
> ошибками
Код тот приведен для думающих программеров, а не для слепого "передирания"
> Хоть бы дописали тогда:
> П.С. Доработать напильником :)
Это и ослу понятно.
Ты есть осел ?)
← →
DmitriyR (2006-06-19 15:23) [7]> Код тот приведен для думающих программеров, а не для слепого "передирания"
> Это и ослу понятно.
> Ты есть осел ?)
Я тебе очень признателен за помощь но наежать так не надо!
я еще в предыдущих ответах писал:
> сильно не пинайте я не профи я токо учусь :)
Понятие думающих сильно отличается от наших взглядов.
Поясни плиз как может додуматся какой ставить знак в етом коде
(а таких мест с ошибками там около 10)
if iWAIT_OBJECT_0 then
goto Error;
ето понятно что между i и WAIT_OBJECT_0 должно чтото быть но
новичек (тоесть человек который плохо разбирается но ему ето надо и он учится на пробах и ошибках без помощи знающих тут просто сядет в лужу)
Понятие слепого "передирания" ето взял, воткнул, не пошло, выкинул. А думающий (или хоть как то пытающийся понять человек ищет ответ если сам не может спрашивает у знающих).
Да я токо учусь и поетому прошу помощи здесь на форуме для того он и есть.
Вопрос остается открытый: как вызвать ету процедуру правильно чтобы можно было посылать и получать данные в/из консольного приложения.
← →
Сергей М. © (2006-06-19 15:42) [8]
> наежать так не надо!
> я еще в предыдущих ответах писал:
> > сильно не пинайте я не профи я токо учусь :)
Разуй глаза - для тебя на этом сайте есть спецфорум "Начинающие".
Почему ты здесь , а не в том самом форуме ?
> ето понятно что между i и WAIT_OBJECT_0 должно чтото быть
А раз тебе это понятно, то следующим твоим шагом должен был быть скв.поиск текстовых файлов, содержащих симв.идентификатор WAIT_OBJECT_0.
> думающий (или хоть как то пытающийся понять человек ищет
> ответ
Неправильно ты его ищешь, этот "ответ", не своей головой .. чужой ..
> как вызвать ету процедуру правильно
Покажи как ты ее вызываешь "неправильно" ..
← →
DmitriyR (2006-06-19 17:09) [9]Вызываю просто создаю отдельный поток:
var
hThread: HWND;
ThID: Cardinal;
procedure ......
begin
hThread := CreateThread(nil, 0, @ExecuteFile(FileName,1000), nil, 0, ThID);
end;
При етом я изменил функцию:
function ExecuteFile(FileName: string;
TimeOut: integer) : boolean;
Но я не знаю как стелать правильный вызов чтоб получить и ввод и вывод данных. Тоесть StdInput и StdOutput как быть с ними не знаю.
Занес их в глобальные переменные пока чтоб ошибка не выходила.
← →
DmitriyR (2006-06-19 17:18) [10]Сразу исправлюсь.
Запускаю отдельный поток а в етом потоке уже стартую ету функцию.
← →
DmitriyR (2006-06-19 17:32) [11]Блин скоко ж тут ошибок :(
Сергей М
вы мне помогли но тоже допустили ошибку в етом куске кода надо вот так:
begin
CloseHandle(ProcInf.hThread);
i := WaitForSingleObject(ProcInf.hProcess, 1000);
CloseHandle(ProcInf.hProcess);
if i <> WAIT_OBJECT_0 then
^^ а не = как вы посоветовали.
← →
Belorus © (2006-06-19 20:32) [12]А ты что хотел чтобы тебе бесплатно помогли без ошибок и не нахамили ?
Хе-хе
← →
Сергей М. © (2006-06-20 10:53) [13]
> создаю отдельный поток
> CreateThread
На то есть класс TThread, в кр.случае - ф-ция BeginThread().
CreateThread() не рекомендуется использовать по ряду важных соображений.
> При етом я изменил функцию
Поточная ф-ция должна иметь строго определенный прототип, отсебячина с параметрами и соглашениями о вызове здесь не допускается.
type
PMyParameters = ^TMyParameters;
TMyParameters = packed record
FileName, StdInput, StdOutput: String;
Timeout: Integer;
end;
var
MyParameters: TMyParameters;
ThreadFuncResult: Longbool;
...
function MyThreadFunc(Parameters: PMyParameters): Longbool;
begin
with Parameters^ do
try
Result := ExecuteFile(FileName, StdInput, Timeout, StdOut);
except
end;
end;
...
with MyParameters do
begin
FileName := ...;
StdInput := ...;
Timeout := ...;
end;
hThread := BeginThread(nil, 0, @MyThreadFunc, nil, 0, ThID);
while WaitForSingleObject(hThread, 10) <> WAIT_OBJECT_0 do
Application.Processmessages;
GetExitCodeThread(hThread, @ThreadFuncResult);
CloseHandle(hThread);
← →
Дмитрий Белькевич © (2006-06-21 01:38) [14]По поводу обработки напильником: как правило, почти любой код, приведенный в нете, нужно (иногда долго) полировать тем самым напильником. НО! Идея - вот что главное в коде, часто не доведенная до конца. Вспоминаю один свой интересный случай - алгоритм поиска всех файлов в папке/на венике. Казалось бы: что проще? Тривиальный обход дерева. Шоб не изобретать очередной TVelosiped, воткнул чью-то реализацию. Через некоторое время от некоторых пользовтелей посыпались жалобы - мол, плохо диски сканирует, на некоторых файлов вообще не видит. Ну как уже себя не гонял, какие тесты не придумывал - работал алгоритм идеально. В конце концов поменял вообще кусок кода на другой (без рекурсии) всё - проблем с тех пор нет. Что там была за проблема, я, к сожалению, так и не узнал.
Так что к каждому коду (из инета) нужно подходить критически, а не бездумно ctrl-v ctrc-c.
← →
divNULL (2006-06-27 15:36) [15]У меня такая же проблема и тоже не могу разобраться с пайпами. Здесь можно обойтись и без них. Для того чтобы получить ответы от CMD.exe вызывай его так "путь\cmd.exe /с комманды > c:\111.txt". Здесь комманды которые нужно передать CMD пишутся после "/c" , а ">" указывает что все выходные данные будут печататься в файл 111.txt. А из файла их взять я думаю не проблема. Только вот такое решение мне кажется каким-то корявым, необходимо создавать файл. Вобщем если придумаеш что получше то напиши сюда или на мылою.
Страницы: 1 вся ветка
Текущий архив: 2006.07.16;
Скачать: CL | DM;
Память: 0.51 MB
Время: 0.008 c