![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
итак. есть некая утилита которая работает через командную строку.
моё приложение написанное на дельфи посылает ей команды, используя найденную в сети функцию GetDosOutput. если команда успешно отработана,то утилита ничего не возвратит,то есть пустую строку.если же при выполении команды произошла ошибка то вернется сообщение об ошибке. Соответственно я проверяю возвращаемый рез-тат и если он пустой,значит команда успешна,значит моя прога продолжает что либо делать. Но вот незадача,в одном месте эта сторонняя утилита завершается с ошибкой,то есть не просто выводит в ответ сообщение об ошибке что немогу выполнить команду, а резко завершается,сбой какойто.и в ответ моя функция не получает сообщение с ошибкой а получает пустой результат, и я незнаю как определить что это пустой результат в случае успешного выполнения команды,или же это пустота изза того что процесс утилиты резко завершился. Может как то можно проверить что процесс вызванный функцией GetDosOutput завершился преждевременно. И ещё,при такой ошибке на экране появляется сообщение от винды7 что эта утилита завершилась (не моя прога а сторонняя утилита) Возникшая проблема привела к прекращению работы программы. Windows закроет эту программу, а если есть известный способ устранения проблемы, уведомит вас об этом. - можно ли это сообщение както скрыть от глаз юзера? вот сама функция Код:
function GetDosOutput(CommandLine,Parametrs: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+' '+Parametrs), nil,nil,True,0,nil,PChar(WorkDir),SI,PI);
// Теперь, когда дескриптор получен, для безопасности закрываем запись.
// Нам не нужно, чтобы произошло случайное чтение или запись.
CloseHandle(StdOutPipeWrite);
// если процесс может быть создан, то дескриптор, это его вывод
if not WasOK then begin
Line:='Could not execute';
end
else
try
// получаем весь вывод до тех пор, пока DOS-приложение не будет завершено
Line := '';
repeat //считывает ответ после выполнения команды
// читаем блок символов (могут содержать возвраты каретки и переводы строки)
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
// есть ли что-нибудь ещё для чтения?
if BytesRead > 0 then
begin
// завершаем буфер PChar-ом
Buffer[BytesRead] := #0;
//Form1.Memo1.Lines.Add(Buffer);
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; |
|
#2
|
||||
|
||||
|
попробуй посмотреть результат WaitForSingleObject, особенно когда он WAIT_FAILED, далее смотреть GetLastError. так же можно посмотреть на результат GetExitCodeProcess.
|
|
#3
|
||||
|
||||
|
что-то не могу минимальный проект реализовать
![]() "сторонняя программа" вызывает ошибку: Код:
program ProjCons;
{$APPTYPE CONSOLE}
var
a, b, c: Integer;
begin
Readln;
a:=0;
b:=0;
try
c:=a div b;
except
c:=0;
end;
Writeln(c);
Readln;
end.но GetDosOutput возвращает текст "Runtime error 6 at 00403A52" ![]() ну да ладно с этим... а вот GetExitCodeProcess как раз возвращает 6 |
| Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
Snake22 (12.10.2012)
| ||
|
#4
|
|||
|
|||
|
Цитата:
в случае норм выполнения возвращает ноль а при ошибке 3221225477. спасибо! =) |
|
#5
|
|||
|
|||
|
а можно ли както еще сделать чтоб не вылезало окно винды сообщающее что утилита была остановлена?
![]() Если надо скину утилиту с командой вызывающей крах/ может вот здесь что-то указать надо?какой нить флаг например: Код:
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; |
|
#6
|
||||
|
||||
|
это в настройках Windows отключается. свойства системы - отчет об ошибках.
|
|
#7
|
||||
|
||||
|
Есть еще такая штука, как перехват системой исключений в консольных приложениях, см. InitExceptions/DoneExceptions. Правда, это в своем приложении, и не уверен, что будет работать в порожденном процессе.
|