如何让Dos下的屏幕输出信息取得并且显示在Dialog的Edit框中?请教用哪个API可以实现?

wangxiaokaiasdf 2003-09-29 10:49:18
我用system写在按钮事件里头,执行了一个Dos命令,可是想把执行Dos命令后的屏幕
输出信息显示在自己设计的对话框上,应该如何来做,用什么函数?
...全文
258 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
Skt32 2003-10-03
  • 打赏
  • 举报
回复
“模拟”DOS

如需转载请与作者联系


--------------------------------------------------------------------------------

作者姓名:胡金山

邮件地址: tohjs@163.com
作者相关信息:空军工程大学工程学院

代码下载



开发环境: VC6 Windows 2000
测试环境:Windows 2000 WindowsXP



Windows2K的控制台窗口用起来已经很方便了,但是在应用程序窗口里边进行控制台的输入输出还是比较有意思的。该程序运行如图:



接收输入输出的功能用Pipe技术在一个由CEditView类派生来的CconsoleView类实现实现。重要的成员函数有:

1.重定向子进程的输入输出:

BOOL CConsoleView::CreateConsoleRedirect()

{

SECURITY_ATTRIBUTES saAttr;

BOOL fSuccess;

// Set the bInheritHandle flag so pipe handles are inherited.

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;

}

// 复制写句柄到管道,这样它就不可继承

// Duplicate the write handle to the pipe so it is not inherited.

fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,

GetCurrentProcess(), &hChildStdinWrDup,

0, FALSE, // not inherited

DUPLICATE_SAME_ACCESS );

if( !fSuccess )

{

TRACE0( _T("DuplicateHandle failed\n") );

return FALSE;

}

CloseHandle(hChildStdinWr);

// 创建子进程

if( !CreateChildProcess(dwProcessId) )

{

TRACE0( _T("CreateChildProcess failed\n") );

return FALSE;

}

// 子进程创建完毕,重置系统标准输入输出

if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )

{

TRACE0( _T("Re-redirecting Stdin failed\n") );

return FALSE;

}

if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )

{

TRACE0( _T("Re-redirecting Stdout failed\n") );

return FALSE;

}

m_pReadThread = AfxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this );

if( !m_pReadThread )

{

TRACE0( _T("Cannot start read-redirect thread!\n") );

return FALSE;

}

return TRUE;

}

2.创建子进程:

BOOL CConsoleView::CreateChildProcess(DWORD& dwProcessId)

{

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;

TCHAR shellCmd[_MAX_PATH];

if( !GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH) )

return FALSE;

#ifdef _UNICODE

_tcscat( shellCmd, _T(" /U") );

#else

_tcscat( shellCmd, _T(" /A") );

#endif

// 创建子进程

BOOL ret = CreateProcess( NULL,

shellCmd, // applicatin name

NULL, // process security attributes

NULL, // primary thread security attributes

TRUE, // handles are inherited

DETACHED_PROCESS, // creation flags

NULL, // use parent's environment

NULL, // use parent's current directory

&siStartInfo, // STARTUPINFO pointer

&piProcInfo); // receives PROCESS_INFORMATION

if( ret )

dwProcessId = piProcInfo.dwProcessId;

return ret;

}

3.写入到管道:

void CConsoleView::WriteToPipe( LPCTSTR line )

{

DWORD dwWritten;

WriteFile( hChildStdinWrDup, line, _tcslen(line)*sizeof(TCHAR),

&dwWritten, NULL );

}

4.读管道线程函数:

UINT CConsoleView::ReadPipeThreadProc( LPVOID pParam )

{

DWORD dwRead;

TCHAR chBuf[BUFSIZE];

CConsoleView* pView = (CConsoleView*)pParam;



TRACE0( _T("ReadPipe Thread begin run\n") );

for( ;; )

{

if( !ReadFile( pView->hChildStdoutRdDup, chBuf,

BUFSIZE, &dwRead, NULL) || dwRead == 0)

break;

chBuf[dwRead/sizeof(TCHAR)] = _T('\0');

pView->AddTexts( chBuf );

pView->m_nLength = pView->GetEditCtrl().SendMessage( WM_GETTEXTLENGTH );

}

CloseHandle( pView ->hChildStdinRd);

CloseHandle( pView ->hChildStdoutWr);

CloseHandle( pView ->hChildStdinWrDup );

CloseHandle( pView ->hChildStdoutRdDup );

pView->m_pReadThread = NULL;

pView->dwProcessId = DWORD(-1);

pView->PostMessage( WM_CLOSE );

return 1;

}

5.退出程序时清除进程、线程:

void CConsoleView::OnDestroy()

{

if( dwProcessId!=DWORD(-1) )

{

HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId );

if( hProcess )

{

TerminateProcess( hProcess,0 );

CloseHandle( hProcess );

}

}

if( m_pReadThread )

{

TerminateThread( m_pReadThread->m_hThread,0 );

delete m_pReadThread;

}

CEditView::OnDestroy();

}

事实上,这个程序非常简单,干净利落,关键之处就在于上述几个成员函数。具体代码请参阅附带工程文件。值得注意的是当输入DOS命令cls时,程序应当清除之前接收的文本,输入DOS命令exit时,退出程序。可能还有其它的DOS命令要特别应对,笔者没有细究。

http://vchelp.net/vchelp/file2003_3/console.asp?type_id=73&class_id=1&cata_id=2&article_id=1008&search_term=
Skt32 2003-09-29
  • 打赏
  • 举报
回复
输出重定向
Skt32 2003-09-29
  • 打赏
  • 举报
回复
http://www.codeguru.com/misc/RedirectOutputToPipe.shtml
This article was contributed by Xinhai Kang.
Environment: Visual C++ 6.0 SP2, Windows NT 4.0 SP4



I have the thought of redirecting output of WIN32 console programs to a pipe or a file long ago, but I don't know to do at all at first, finally I searched through Microsoft MSDN and found a way, the code pasted below was copied from MSDN sample code except some changes in function CreateChildProcess(), where I stressed in the code.

In the demo source, I redirect the stdout of CMD.exe to a pipe and start a thread to read from this pipe, then all that CMD.EXE output was redirected to the pipe where I am reading.



BOOL CShellView::CreateShellRedirect()
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;

// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

// The steps for redirecting child process's STDOUT:
// 1. Save current STDOUT, to be restored later.
// 2. Create anonymous pipe to be STDOUT for child process.
// 3. Set STDOUT of the parent process to be write handle to
// the pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle.

// Save the handle to the current STDOUT.
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);

// Create a pipe for the child process's STDOUT.
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
TRACE0( _T("Stdout pipe creation failed\n") );
return FALSE;
}

// Set a write handle to the pipe to be STDOUT.
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
TRACE0( _T("Redirecting STDOUT failed\n") );
return FALSE;
}

// Create noninheritable read handle and close the inheritable read handle.
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle( hChildStdoutRd );

// The steps for redirecting child process's STDIN:
// 1. Save current STDIN, to be restored later.
// 2. Create anonymous pipe to be STDIN for child process.
// 3. Set STDIN of the parent to be the read handle to the
// pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the write handle,
// and close the inheritable write handle.

// Save the handle to the current STDIN.
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

// Create a pipe for the child process's STDIN.
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
TRACE0( _T("Stdin pipe creation failed\n") );
return FALSE;
}
// Set a read handle to the pipe to be STDIN.
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
TRACE0( _T("Redirecting Stdin failed\n") );
return FALSE;
}
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle(hChildStdinWr);

// Now create the child process.
if( !CreateChildProcess(dwProcessId) )
{
TRACE0( _T("CreateChildProcess failed\n") );
return FALSE;
}
// After process creation, restore the saved STDIN and STDOUT.
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
TRACE0( _T("Re-redirecting Stdin failed\n") );
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
TRACE0( _T("Re-redirecting Stdout failed\n") );
return FALSE;
}
m_pReadThread =
fxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this );
if( !m_pReadThread )
{
TRACE0( _T("Cannot start read-redirect thread!\n") );
return FALSE;
}
return TRUE;
}

BOOL CShellView::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;

// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
/////////////////////////////////////////
/*
Note here the
dwFlags should be STARTF_USESTDHANDLES, which is descripted in WIN32 API
document, but this was
omitted in MSDN sample
*/
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;

///////////////////////////////////////////////////
TCHAR shellCmd[_MAX_PATH];
if( !GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH) )
return FALSE;
#ifdef _UNICODE
_tcscat( shellCmd, _T(" /U") );
#else
_tcscat( shellCmd, _T(" /A") );
#endif
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}


Download source - 5 KB

Date Last Updated: April 4, 1999

Comments:
pop up a console window - iop (2003/02/28)
Redirect Output of CMD.EXE to a Pipe - Cheng Chao (2002/08/27)
Not coming out of Thread's for loop - shimsha_r (2001/01/16)
sending commands to stdin ? - Johnny J (2000/10/23)
not included all the header files !!!!! - simran bir singh (2000/05/03)
Do you know how to achieve the same... asynchronously? - Jason Hattingh (1999/07/06)
Works for Win9x and WinNT now - Uwe Kotyczka (1999/07/05)
It would be great if you could provide the demo project - Xiaojian Liu (1999/07/05)
WHERE IS THE GURUEDITOR.H ? HOW CAN I COMPILE IT OK? - KONG (1999/06/14)
Class CExecute - Xinhai Kang (1999/04/08)
Under Win9x - Yangghi Min (1999/04/07)
Win95 can be done - John Young (1999/04/07)
Win95 too ! - Shark (1999/04/06)
Win95 too? - Troels (1999/04/05)
Add Comment

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧