Показать сообщение отдельно
  #1  
Старый 12.10.2012, 14:23
Snake22 Snake22 вне форума
Активный
 
Регистрация: 20.02.2011
Сообщения: 374
Репутация: 744
По умолчанию отловить ошибку при вызове из проги cmd команды

итак. есть некая утилита которая работает через командную строку.
моё приложение написанное на дельфи посылает ей команды, используя найденную в сети функцию 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;
Ответить с цитированием