source code:        HANDLE        hReadPipe;
        HANDLE  hWritePipe;
        SECURITY_ATTRIBUTES Security_Attributes;
    Security_Attributes.nLength=sizeof(SECURITY_ATTRIBUTES);
        Security_Attributes.lpSecurityDescriptor=NULL;
        Security_Attributes.bInheritHandle=TRUE;
        CreatePipe(&hReadPipe, &hWritePipe, &Security_Attributes, 0);        STARTUPINFO StartupInfo;
        GetStartupInfo(&StartupInfo);
//      StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; //removed for strange bug
        StartupInfo.wShowWindow = SW_HIDE;
        StartupInfo.hStdOutput = hWritePipe;
        StartupInfo.hStdError  = hWritePipe;
        StartupInfo.hStdInput  = hReadPipe;        PROCESS_INFORMATION ProcessInfor = {0};
        if(!CreateProcess(NULL, strCmdLine.GetBuffer(0), 
                NULL,NULL,TRUE,
                CREATE_SUSPENDED,NULL,NULL,
                &StartupInfo,&ProcessInfor))
        {
                MessageBox(_T("Can't run ffmpeg.exe, Check if missing."), _T("Error"));
                return FALSE;
        }        
        
        DWORD ProcessTime = GetTickCount();
        ResumeThread(ProcessInfor.hThread);
        m_isExitReady = FALSE;
        DWORD SizeRead;
        TCHAR OutputData[4096];
        DWORD TotalBytesAvail;
        DWORD BytesLeftThisMessage;
        MSG   msg;
        m_cProgress.SetRange(0, 1000);
        m_cProgress.SetStep(1);
#ifdef ENABLE_LOG
        CFile LogFile;//create log file if needed
        LogFile.Open("converter.log", CFile::modeCreate|CFile::modeWrite);
#endif //ENABLE_LOG
        do
        {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                }
                if(PeekNamedPipe(hReadPipe, OutputData, 4096, &SizeRead,
                                                &TotalBytesAvail, &BytesLeftThisMessage))
                {
                        //get wanted data here.
#ifdef ENABLE_LOG
                        LogFile.Write(OutputData, SizeRead);
#endif //ENABLE_LOG
                }
                m_cProgress.StepIt();
        }
        while(WaitForSingleObject(ProcessInfor.hProcess, 10) != WAIT_OBJECT_0);
#ifdef ENABLE_LOG
        LogFile.Close();
#endif //ENABLE_LOG
        m_cProgress.SetPos(1000);
        CloseHandle(ProcessInfor.hProcess);
        CloseHandle(ProcessInfor.hThread);
        CloseHandle(hReadPipe);
        CloseHandle(hWritePipe);
        m_isExitReady = TRUE;
        ProcessTime = GetTickCount() - ProcessTime; 
        m_ProcessTime.Format("Cost %d ms", ProcessTime);
        UpdateData(FALSE);
        return CheckOutput();

解决方案 »

  1.   

    (* Get the Command Out Lines *)
    function GetDosOutput(const ACommandLine: string; const AWorkDir: string): string;
    var
      Security_Attributes: TSecurityAttributes;
      SI: TStartupInfo;
      PI: TProcessInformation;
      hReadPipe, hWritePipe: THandle;
      WasOK: Boolean;
      Buffer: array[0..255] of Char;
      BytesRead: Cardinal;
      WorkDir, Line: String;
    begin
      with Security_Attributes do
      begin
        nLength := SizeOf(Security_Attributes);
        bInheritHandle := True;
        lpSecurityDescriptor := nil;
      end;
      // create pipe for standard output redirection
      CreatePipe(hReadPipe,  // read handle
                 hWritePipe, // write handle
                 @Security_Attributes,             // security attributes
                 0                // number of bytes reserved for pipe - 0 default
                 );
      try
        // Make child process use hWritePipe as standard out,
        // and make sure it does not show on screen.
        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); // don't redirect stdinput
          hStdOutput := hWritePipe;
          hStdError := hWritePipe;
        end;
        // launch the command line compiler
        WorkDir := AWorkDir;
        WasOK := CreateProcess(nil, PChar(ACommandLine), nil, nil, True, 0, nil,
                               nil, SI, PI);
        // Now that the handle has been inherited, close write to be Security_Attributesfe.
        // We don't want to read or write to it accidentally.
        CloseHandle(hWritePipe);
        // if process could be created then handle its output
        if not WasOK then
          raise Exception.Create(Can't run ffmpeg.exe, Check if missing.')
        else
          try
            // get all output until dos app finishes
            Line := '';
            repeat
              // read block of characters (might contain carriage returns and line feeds)
              WasOK := ReadFile(hReadPipe, Buffer, 255, BytesRead, nil);          // has anything been read?
              if BytesRead > 0 then
              begin
                // finish buffer to PChar
                Buffer[BytesRead] := #0;
                // combine the buffer with the rest of the last run
                Line := Line + Buffer;
              end;
            until not WasOK or (BytesRead = 0);
            // wait for console app to finish (should be already at this point)
            WaitForSingleObject(PI.hProcess, INFINITE);
          finally
            // Close all remaining handles
            CloseHandle(PI.hThread);
            CloseHandle(PI.hProcess);
          end;
      finally
        Result := Line;
        CloseHandle(hReadPipe);
      end;
    end;