Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.07.16;
Скачать: [xml.tar.bz2];

Вниз

Запуск программ с передачей консольного ввода и чтением вывода   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.009 c
4-1144143828
Babay
2006-04-04 13:43
2006.07.16
Сменить фон TreeView


3-1147356242
Boris Marchenko
2006-05-11 18:04
2006.07.16
Ошибка при залогинивании в IBConsole


2-1151336611
b.o.n.d.007
2006-06-26 19:43
2006.07.16
Не понимаю циклы. Помогите.


2-1151313933
GrBob
2006-06-26 13:25
2006.07.16
WMI - самое начало.


2-1151653268
fast2
2006-06-30 11:41
2006.07.16
Как вывести в Label содерживое ячейки 2-го столбца...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский