我在程序中用CreateProcess()执行一个DOS程序,这个DOS程序有屏幕输出,为此,我先用CreatePipe()创建了一个管道,在CreateProcess()函数中设置屏幕(标准)输出重定向到刚创建的管道。
为了读取管道内的数据,我用CreateThrea()创建了一个线程,并向这个线程过程传递一个管道的“读句柄”。
问题:
1 代码如何组织?
2 DOS程序结束了,线程还在不停的读,如何判断DOS程序结束,又如何让线程停下来?
为了读取管道内的数据,我用CreateThrea()创建了一个线程,并向这个线程过程传递一个管道的“读句柄”。
问题:
1 代码如何组织?
2 DOS程序结束了,线程还在不停的读,如何判断DOS程序结束,又如何让线程停下来?
解决方案 »
- VC++高手,看看吧!
- MFC程序写哪儿?
- 如何让显示在视图里的图片不会因视图的改变而消失(比如说最大化)?
- 困惑,为什么我的线程不能执行?
- 怎麼不能改變顏色??((CEdit *)GetDlgItem(IDC_EDIT_INMIN1))->GetDC()->SetBkColor(RGB(255,0,0))
- 基于CFormView的SDI工程
- 为什么《程序员大本营》里的VS SP5不能安装?提示是语言不符合。
- help!如何在VC中创建一个service application.谢了!
- 如何计算字符串draw出来的真实宽度(象素)?
- 我快要崩溃了,请教dll 调用问题
- 如何改变静态标签的颜色
- InvokeHelper函数是做什么用的?????
DWORD WINAPI RunWritePipeThread(PVOID wParam)
{
DWORD dwRead;
CDataStream* pHandle = (CDataStream*)wParam;
char temp[400];
memset(temp, '\0', 400);
TRACE0( _T("ReadPipe Thread begin run\n") );
int len = 0;
memset(pHandle->chBuf, '\0', 4096);
for( ;; )
{
memset(temp, '\0', 400);
if( !ReadFile(pHandle->hChildStdoutRdDup, temp,
400, &dwRead, NULL) || dwRead == 0)
{
break;
}
if((len + dwRead) > 4096)
{
break;
}
memcpy(pHandle->chBuf + len, temp, dwRead);
len = len + dwRead;
} CloseHandle( pHandle->hChildStdinRd);
CloseHandle( pHandle->hChildStdoutWr);
CloseHandle( pHandle->hChildStdinWrDup );
CloseHandle( pHandle->hChildStdoutRdDup );
pHandle->dwProcessId = DWORD(-1);
return 0;
}BOOL CDataStream::CreateChildProcess(DWORD &dwProcessId, const char* arg)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo; ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;
int len = strlen(arg);
CString strCommand = _T("d:\\DataStream.exe");
BOOL ret = CreateProcess(NULL, strCommand.GetBuffer(), NULL, NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&siStartInfo,&piProcInfo);
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}BOOL CDataStream::LogOpt(const char *arg)
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL; // 重定向子进程的标准输出...
// 保存当前标准输出的句柄
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
//为子进程的标准输出创建一个管道
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
TRACE0( _T("Stdout pipe creation failed\n") );
return false;
}
// 设置一个写句柄到管道,使之成为标准输出
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
TRACE0( _T("Redirecting STDOUT failed\n") );
return false;
}
// 创建不可继承的读句柄并关闭可继承的读句柄
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return false;
}
CloseHandle( hChildStdoutRd ); hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); //为子进程的标准输入创建一个管道
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
TRACE0( _T("Stdin pipe creation failed\n") );
return false;
}
// 设置一个写句柄到管道,使之成为标准输入
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
TRACE0( _T("Redirecting Stdin failed\n") );
return false;
}
// 复制写句柄到管道,这样它就不可继承
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return false;
}
CloseHandle(hChildStdinWr);
AfxBeginThread( (AFX_THREADPROC)RunWritePipeThread,(LPVOID)this );
Sleep(10);
if(CreateChildProcess(dwProcessId, arg))
{
return true;
}
return false;
}