Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Консольное приложение


Автор: XperT 28.8.2006, 23:13
У меня есть програма консольная. Я решил для неё сделать графический интерфейс, но так как у меня исходников нету, то соответственно в идеале не получится  smile 

Вообщем суть проблемы такова:
Програма (та что консольная) в процесе работы имитирует процес бар, ну и сбоку пишет процент выполнения. Как мне в ходе ее работы перехватывать тот процент и посылать его на свой графический процес бар?

Автор: Snowy 29.8.2006, 00:07
Захватывать вывод консоли: http://vingrad.ru/DELPHI-DLP-000823

Автор: XperT 29.8.2006, 11:59
Код

unit consoleoutput;  

interface 

uses 
 Controls, Windows, SysUtils, Forms; 

function GetDosOutput(const CommandLine:string): string; 

implementation 

function GetDosOutput(const CommandLine:string): string; 
var 
 SA: TSecurityAttributes; 
 SI: TStartupInfo; 
 PI: TProcessInformation; 
 StdOutPipeRead, StdOutPipeWrite: THandle; 
 WasOK: Boolean; 
 Buffer: array[0..255] of Char; 
 BytesRead: Cardinal; 
 WorkDir, Line: String; 
begin 
 Application.ProcessMessages; 
 with SA do 
 begin 
   nLength := SizeOf(SA); 
   bInheritHandle := True; 
   lpSecurityDescriptor := nil; 
 end; 
 // создаём пайп для перенаправления стандартного вывода 
 CreatePipe(StdOutPipeRead,  // дескриптор чтения 
            StdOutPipeWrite, // дескриптор записи 
            @SA,              // аттрибуты безопасности 
            0                // количество байт принятых для пайпа - 0 по умолчанию 
            ); 
 try 
   // Создаём дочерний процесс, используя StdOutPipeWrite в качестве стандартного вывода, 
   // а так же проверяем, чтобы он не показывался на экране. 
   with SI do 
   begin 
     FillChar(SI, SizeOf(SI), 0); 
     cb := SizeOf(SI); 
     dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
     wShowWindow := SW_HIDE; 
     hStdInput := GetStdHandle(STD_INPUT_HANDLE); // стандартный ввод не перенаправляем 
     hStdOutput := StdOutPipeWrite; 
     hStdError := StdOutPipeWrite; 
   end; 

   // Запускаем компилятор из командной строки 
   WorkDir := ExtractFilePath(CommandLine); 
   WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil, PChar(WorkDir), SI, PI); 

   // Теперь, когда дескриптор получен, для безопасности закрываем запись. 
   // Нам не нужно, чтобы произошло случайное чтение или запись. 
   CloseHandle(StdOutPipeWrite);  
   // если процесс может быть создан, то дескриптор, это его вывод 
   if not WasOK then 
     raise Exception.Create('Could not execute command line!') 
   else 
     try 
       // получаем весь вывод до тех пор, пока DOS-приложение не будет завершено 
       Line := ''; 
       repeat 
         // читаем блок символов (могут содержать возвраты каретки и переводы строки) 
         WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); 

         // есть ли что-нибудь ещё для чтения? 
         if BytesRead > 0 then 
         begin 
           // завершаем буфер PChar-ом 
           Buffer[BytesRead] := #0; 
           // добавляем буфер в общий вывод 
           Line := Line + Buffer; 
         end; 
       until not WasOK or (BytesRead = 0); 
       // ждём, пока завершится консольное приложение 
       WaitForSingleObject(PI.hProcess, INFINITE); 
     finally 
       // Закрываем все оставшиеся дескрипторы 
       CloseHandle(PI.hThread); 
       CloseHandle(PI.hProcess); 
     end; 
 finally 
     result:=Line; 
     CloseHandle(StdOutPipeRead); 
 end; 
end; 


end. 


Насколько я понял, то я получу только конечный результат, тоесть текст после завершения роботы програмы, а мне нужно в процесе работы програмы перехватывать даные.

Автор: Romikgy 29.8.2006, 12:13
Цитата(XperT @  29.8.2006,  10:59 Найти цитируемый пост)
а мне нужно в процесе работы програмы перехватывать даные.

ну и че приведеный код это не позволяет делать ?

Автор: dumb 29.8.2006, 12:33
есть подозрение, что консольное приложение работает напрямую с консолью(WriteConsoleOutput), а не через стандартные дескрипторы. ловить такое наверное проще всего через перехват консольных функций.

Автор: XperT 29.8.2006, 13:18
Цитата(Romikgy @  29.8.2006,  12:13 Найти цитируемый пост)
ну и че приведеный код это не позволяет делать ? 


Я в этом коде мало что понял. Можешь просто указать на строчку с которой можно тянуть даные или навести какой то элементарный пример выходя из которого я смог бы реализовать то что мне нужно?

Автор: Snowy 29.8.2006, 13:29
Ну так переделай под свои нужны.
Чтение идёт в цикле.
Вот в цикле и работай.
Данный вариант выдаёт результат по завершении программы.
Но ничего не мешает встроиться в цикл и обрабатывать данные, читаемые там.

Автор: Romikgy 29.8.2006, 13:55
Цитата(XperT @  29.8.2006,  12:18 Найти цитируемый пост)
с которой можно тянуть даные


Цитата(XperT @  29.8.2006,  10:59 Найти цитируемый пост)
ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);


Автор: XperT 29.8.2006, 15:48
Не получается. Я думаю проблема в следущем:

Эта консольная полоса процеса с процентами после завершения пропадает, и её заменяет текст (ну там типа всё прошло удачно). 

Я пытался считать с этой строки ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); буфер, но получал только текст который идёт уже после того как полоса прогреса пропадает. 

Автор: Romikgy 29.8.2006, 15:55
тогда ищи окно этой консоли и забирай данные с этой консоли

Автор: XperT 29.8.2006, 16:09
Цитата(Romikgy @  29.8.2006,  15:55 Найти цитируемый пост)
тогда ищи окно этой консоли и забирай данные с этой консоли 


Пример если не сложно дай пожалуйста.

Автор: Romikgy 29.8.2006, 16:23
а ты скрин дай твоего окна, дабы напрасно не писать пример

Автор: XperT 29.8.2006, 16:37
До (когда есть полоса прогреса):

user posted image

После:

user posted image

Автор: Snowy 29.8.2006, 16:41
Мог бы так и сказать, что UPX.
Он же с открытым кодом.
Нафига мучаться?

Автор: Romikgy 29.8.2006, 16:44
странно что не работает первый код

Автор: XperT 29.8.2006, 16:47
Цитата(Snowy @  29.8.2006,  16:41 Найти цитируемый пост)
Мог бы так и сказать, что UPX.
Он же с открытым кодом.
Нафига мучаться? 


Ну вообще то это я для себя, хочу разобратся с тем как работать с консольными програмами, точнее как для уже существующей делать достойный GUI. А взял UPX потому что часто им пользуюсь, вот и решил совместить приятное с полезным.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)