Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.53 MB
Время: 0.112 c
2-1151109122
Maggot
2006-06-24 04:32
2006.07.16
Послать *.doc на печать.Подскажите пожалуйста!


15-1150393800
TUser
2006-06-15 21:50
2006.07.16
Плагин бы ...


1-1149229801
Layner
2006-06-02 10:30
2006.07.16
Balloon Hint не хочет показываться :( В чем может быть дело..


2-1151503487
novill
2006-06-28 18:04
2006.07.16
Почему из сервиса(службы) с админскими правами не могу выключить


2-1151499993
medved_68
2006-06-28 17:06
2006.07.16
Посылка сообщения..... ПОДСКАЖИТЕ ПЛЗ!!!!!!