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();
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();
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;