感谢大侠detrox的代码,实现管道的读出没有问题,代码在http://dev.csdn.net/develop/article/18/18338.shtm 。
但是如何实现管道的读出呢,比如,创进一个 cmd.exe 进程后,向其写入多行命令,如何实现?我用如下代码:
//创建单个进程,通过管道写入命令
SECURITY_ATTRIBUTES sat = {0};
sat.nLength = sizeof( SECURITY_ATTRIBUTES );
sat.lpSecurityDescriptor = NULL;
sat.bInheritHandle = TRUE;
HANDLE hPipeRead=NULL, hPipeWrite=NULL;
BOOL bPipeOk = CreatePipe( &hPipeRead, &hPipeWrite, &sat, NULL );
if( !bPipeOk )
{
return;
}
STARTUPINFO StartUpInfo = {0};
PROCESS_INFORMATION ProInfo = {0};
StartUpInfo.cb = sizeof( StartUpInfo );
StartUpInfo.lpReserved = NULL;
StartUpInfo.dwFlags = 0;
StartUpInfo.cbReserved2 = 0;
StartUpInfo.lpReserved2 = NULL;
StartUpInfo.lpDesktop = NULL;
StartUpInfo.lpTitle = NULL;
StartUpInfo.dwX = 0;
StartUpInfo.dwY = 0;
StartUpInfo.dwXSize = 0;
StartUpInfo.dwYSize = 0;
StartUpInfo.dwXCountChars = 0;
StartUpInfo.dwYCountChars = 0;
StartUpInfo.dwFillAttribute = 0;
StartUpInfo.dwFlags = NULL;//STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
StartUpInfo.wShowWindow = SW_HIDE;
StartUpInfo.hStdInput = hPipeRead;
StartUpInfo.hStdOutput = NULL;//hPipeWrite;
StartUpInfo.hStdError = NULL;//hPipeWrite;
BOOL bProOk = CreateProcess( NULL, "cmd",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
if( !bProOk )
{
bProOk = CreateProcess( NULL, "command",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
}
if( !bProOk )
{
return;
}
CloseHandle( hPipeRead );
char szCmdLine[1024] = {0};
m_edit_command.GetWindowText( szCmdLine, 1020 );
strcat( szCmdLine, "\r\n" );
// 写入命令
ULONG uWrited = 0;
BOOL bWriteOk = WriteFile( hPipeWrite, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
char szWrited[256] = {0};
sprintf( szWrited, "writed: %d", uWrited );
MessageBox( szWrited ); // 关闭进程
// TerminateProcess( ProInfo.hProcess, 0 );
CloseHandle( hPipeRead );
CloseHandle( hPipeWrite );
CloseHandle( ProInfo.hProcess); return;发现,WriteFile写入成功,但并未成功输入cmd窗口中。请大侠指教。
但是如何实现管道的读出呢,比如,创进一个 cmd.exe 进程后,向其写入多行命令,如何实现?我用如下代码:
//创建单个进程,通过管道写入命令
SECURITY_ATTRIBUTES sat = {0};
sat.nLength = sizeof( SECURITY_ATTRIBUTES );
sat.lpSecurityDescriptor = NULL;
sat.bInheritHandle = TRUE;
HANDLE hPipeRead=NULL, hPipeWrite=NULL;
BOOL bPipeOk = CreatePipe( &hPipeRead, &hPipeWrite, &sat, NULL );
if( !bPipeOk )
{
return;
}
STARTUPINFO StartUpInfo = {0};
PROCESS_INFORMATION ProInfo = {0};
StartUpInfo.cb = sizeof( StartUpInfo );
StartUpInfo.lpReserved = NULL;
StartUpInfo.dwFlags = 0;
StartUpInfo.cbReserved2 = 0;
StartUpInfo.lpReserved2 = NULL;
StartUpInfo.lpDesktop = NULL;
StartUpInfo.lpTitle = NULL;
StartUpInfo.dwX = 0;
StartUpInfo.dwY = 0;
StartUpInfo.dwXSize = 0;
StartUpInfo.dwYSize = 0;
StartUpInfo.dwXCountChars = 0;
StartUpInfo.dwYCountChars = 0;
StartUpInfo.dwFillAttribute = 0;
StartUpInfo.dwFlags = NULL;//STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
StartUpInfo.wShowWindow = SW_HIDE;
StartUpInfo.hStdInput = hPipeRead;
StartUpInfo.hStdOutput = NULL;//hPipeWrite;
StartUpInfo.hStdError = NULL;//hPipeWrite;
BOOL bProOk = CreateProcess( NULL, "cmd",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
if( !bProOk )
{
bProOk = CreateProcess( NULL, "command",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
}
if( !bProOk )
{
return;
}
CloseHandle( hPipeRead );
char szCmdLine[1024] = {0};
m_edit_command.GetWindowText( szCmdLine, 1020 );
strcat( szCmdLine, "\r\n" );
// 写入命令
ULONG uWrited = 0;
BOOL bWriteOk = WriteFile( hPipeWrite, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
char szWrited[256] = {0};
sprintf( szWrited, "writed: %d", uWrited );
MessageBox( szWrited ); // 关闭进程
// TerminateProcess( ProInfo.hProcess, 0 );
CloseHandle( hPipeRead );
CloseHandle( hPipeWrite );
CloseHandle( ProInfo.hProcess); return;发现,WriteFile写入成功,但并未成功输入cmd窗口中。请大侠指教。
HANDLE hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
unsigned long lgsize;
WriteFile(hOutput,strbuf,strlen(strbuf),&lgsize,0);
FreeConsole();
PS:楼主的表述有点乱啊
GetStdHandle
ReadConsoleInput
WriteConsoleInput
WriteConsoleOutput
等几个控制台API
StartUpInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
StartUpInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
我是想向cmd进程写入命令,好象应该是设置 hStdInput 吧。
void NewLine(void);
void ScrollScreenBuffer(HANDLE, INT);
HANDLE hStdout, hStdin;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
void main(void)
{
LPSTR lpszPrompt1 = "Type a line and press Enter, or q to quit: ";
LPSTR lpszPrompt2 = "Type any key, or q to quit: ";
CHAR chBuffer[256];
DWORD cRead, cWritten, fdwMode, fdwOldMode;
WORD wOldColorAttrs; // Get handles to STDIN and STDOUT. hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE ||
hStdout == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "GetStdHandle", "Console Error", MB_OK);
return;
} // Save the current text colors. if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
MessageBox(NULL, "GetConsoleScreenBufferInfo",
"Console Error", MB_OK);
return;
} wOldColorAttrs = csbiInfo.wAttributes; // Set the text attributes to draw red text on black background. if (! SetConsoleTextAttribute(hStdout, FOREGROUND_RED |
FOREGROUND_INTENSITY))
{
MessageBox(NULL, "SetConsoleTextAttribute", "Console Error",
MB_OK);
return;
} // Write to STDOUT and read from STDIN by using the default
// modes. Input is echoed automatically, and ReadFile
// does not return until a carriage return is typed.
//
// The default input modes are line, processed, and echo.
// The default output modes are processed and wrap at EOL. while (1)
{
if (! WriteFile(
hStdout, // output handle
lpszPrompt1, // prompt string
lstrlen(lpszPrompt1), // string length
&cWritten, // bytes written
NULL) ) // not overlapped
{
MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
return;
} if (! ReadFile(
hStdin, // input handle
chBuffer, // buffer to read into
255, // size of buffer
&cRead, // actual bytes read
NULL) ) // not overlapped
break;
if (chBuffer[0] == 'q') break;
} // Turn off the line input mode, and echo the input mode. if (! GetConsoleMode(hStdin, &fdwOldMode))
{
MessageBox(NULL, "GetConsoleMode", "Console Error", MB_OK);
return;
} fdwMode = fdwOldMode &
~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (! SetConsoleMode(hStdin, fdwMode))
{
MessageBox(NULL, "SetConsoleMode", "Console Error", MB_OK);
return;
} // Without line and echo input modes, ReadFile returns
// when any input is available. Carriage returns must
// be handled, and WriteFile is used to echo input. NewLine(); while (1)
{
if (! WriteFile(
hStdout, // output handle
lpszPrompt2, // prompt string
lstrlen(lpszPrompt2), // string length
&cWritten, // bytes written
NULL) ) // not overlapped
{
MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
return;
} if (! ReadFile(hStdin, chBuffer, 1, &cRead, NULL))
break;
if (chBuffer[0] == '\r')
NewLine();
else if (! WriteFile(hStdout, chBuffer, cRead,
&cWritten, NULL)) break;
else
NewLine();
if (chBuffer[0] == 'q') break;
} // Restore the original console mode. SetConsoleMode(hStdin, fdwOldMode); // Restore the original text colors. SetConsoleTextAttribute(hStdout, wOldColorAttrs);
}// The NewLine function handles carriage returns when the processed
// input mode is disabled. It gets the current cursor position
// and resets it to the first cell of the next row.
void NewLine(void)
{
if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
MessageBox(NULL, "GetConsoleScreenBufferInfo",
"Console Error", MB_OK);
return;
} csbiInfo.dwCursorPosition.X = 0; // If it is the last line in the screen buffer, scroll
// the buffer up. if ((csbiInfo.dwSize.Y-1) == csbiInfo.dwCursorPosition.Y)
{
ScrollScreenBuffer(hStdout, 1);
} // Otherwise, advance the cursor to the next line. else csbiInfo.dwCursorPosition.Y += 1;
if (! SetConsoleCursorPosition(hStdout,
csbiInfo.dwCursorPosition))
{
MessageBox(NULL, "SetConsoleCursorPosition", "Console Error",
MB_OK);
return;
}
} void ScrollScreenBuffer(HANDLE h, INT x)
{
SMALL_RECT srctScrollRect, srctClipRect;
CHAR_INFO chiFill;
COORD coordDest; srctScrollRect.Left = 0;
srctScrollRect.Top = 1;
srctScrollRect.Right = csbiInfo.dwSize.X - x;
srctScrollRect.Bottom = csbiInfo.dwSize.Y - x;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle is the same as the scrolling rectangle.
// The destination row is left unchanged.
srctClipRect = srctScrollRect;
// Set the fill character and attributes.
chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY;
chiFill.Char.AsciiChar = (char)' ';
// Scroll up one line.
ScrollConsoleScreenBuffer(
h, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill); // fill character and color
}
#include <windows.h>
#include <stdio.h>
#define BUFSIZE 4096
HANDLE hChildStdinRd, hChildStdinWr,
hChildStdoutRd, hChildStdoutWr,
hInputFile, hStdout;
BOOL CreateChildProcess(VOID);
VOID WriteToPipe(VOID);
VOID ReadFromPipe(VOID);
VOID ErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);
DWORD main(int argc, char *argv[])
{
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; // Get the handle to the current STDOUT.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Create a pipe for the child process's STDOUT.
if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
ErrorExit("Stdout pipe creation failed\n"); // Ensure the read handle to the pipe for STDOUT is not inherited. SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);// Create a pipe for the child process's STDIN.
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
ErrorExit("Stdin pipe creation failed\n"); // Ensure the write handle to the pipe for STDIN is not inherited.
SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
// Now create the child process.
fSuccess = CreateChildProcess();
if (! fSuccess)
ErrorExit("Create process failed with"); // Get a handle to the parent's input file.
if (argc == 1)
ErrorExit("Please specify an input file"); printf( "Debug: argv[1] = %s\n", argv[1]); hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if (hInputFile == INVALID_HANDLE_VALUE)
ErrorExit("CreateFile failed");
// Write to pipe that is the standard input for a child process.
WriteToPipe();
// Read from pipe that is the standard output for child process.
ReadFromPipe();
return 0;
}
BOOL CreateChildProcess()
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
// Set up members of the STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bFuncRetn = CreateProcess(NULL,
"cmd", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (bFuncRetn == 0)
ErrorExit("CreateProcess failed\n");
else
{
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return bFuncRetn;
}
}
VOID WriteToPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
// Read from a file and write its contents to a pipe.
for (;;)
{
if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0) break;
if (! WriteFile(hChildStdinWr, chBuf, dwRead,
&dwWritten, NULL)) break;
}
// Close the pipe handle so the child process stops reading.
if (! CloseHandle(hChildStdinWr))
ErrorExit("Close pipe failed\n");
}
VOID ReadFromPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE]; // Close the write end of the pipe before reading from the
// read end of the pipe.
if (!CloseHandle(hChildStdoutWr))
ErrorExit("Closing handle failed");
// Read output from the child process, and write to parent's STDOUT.
for (;;)
{
if( !ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead,
NULL) || dwRead == 0) break;
if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))
break;
}
}
VOID ErrorExit (LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}
(按下某按钮后执行“cmd”,然后写入“dir\r\n”命令,程序报告写入了5个字节,但是cmd窗口没反应)
void CCmdPipeDlg::OnButtonDo()
{
// TODO: Add your control notification handler code here
//创建单个进程,通过管道写入命令
SECURITY_ATTRIBUTES sat = {0};
sat.nLength = sizeof( SECURITY_ATTRIBUTES );
sat.lpSecurityDescriptor = NULL;
sat.bInheritHandle = TRUE;
HANDLE hPipeRead1=NULL, hPipeWrite1=NULL;
HANDLE hPipeRead2=NULL, hPipeWrite2=NULL;
BOOL bPipeOk1 = CreatePipe( &hPipeRead1, &hPipeWrite1, &sat, NULL );
BOOL bPipeOk2 = CreatePipe( &hPipeRead2, &hPipeWrite2, &sat, NULL );
if( !bPipeOk1 || !bPipeOk2 )
{
return;
}
STARTUPINFO StartUpInfo = {0};
PROCESS_INFORMATION ProInfo = {0};
StartUpInfo.cb = sizeof( StartUpInfo );
StartUpInfo.lpReserved = NULL;
StartUpInfo.dwFlags = 0;
StartUpInfo.cbReserved2 = 0;
StartUpInfo.lpReserved2 = NULL;
StartUpInfo.lpDesktop = NULL;
StartUpInfo.lpTitle = NULL;
StartUpInfo.dwX = 0;
StartUpInfo.dwY = 0;
StartUpInfo.dwXSize = 0;
StartUpInfo.dwYSize = 0;
StartUpInfo.dwXCountChars = 0;
StartUpInfo.dwYCountChars = 0;
StartUpInfo.dwFillAttribute = 0;
StartUpInfo.dwFlags = NULL;
StartUpInfo.wShowWindow = SW_SHOW;
StartUpInfo.hStdInput = hPipeRead1;
StartUpInfo.hStdOutput = hPipeWrite2;//NULL;
StartUpInfo.hStdError = hPipeWrite2;//NULL;
BOOL bProOk = CreateProcess( NULL, "cmd",
NULL, NULL, TRUE, NULL, NULL, NULL,
&StartUpInfo, &ProInfo );
if( !bProOk )
{
return;
}
CloseHandle( hPipeRead1 );
CloseHandle( hPipeWrite2 );
char szCmdLine[1024] = "dir\r\n";
// 写入命令
ULONG uWrited = 0;
BOOL bWriteOk = WriteFile( hPipeWrite1, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
char szWrited[256] = {0};
sprintf( szWrited, "writed: %d", uWrited );
MessageBox( szWrited ); // 关闭进程
CloseHandle( hPipeRead2 );
CloseHandle( hPipeWrite1 );
CloseHandle( ProInfo.hProcess); return;
}
void CCmdPipeDlg::OnButtonDo()
{
HANDLE hProcess = ::GetCurrentProcess(); // Set up the security attributes struct.
SECURITY_ATTRIBUTES sa;
::ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE m_hStdIn, m_hStdOut, m_hStdErr;
HANDLE hStdInWriteTmp, hStdOutReadTmp, hStdErrReadTmp;
HANDLE m_hStdInWrite, m_hStdOutRead, m_hStdErrRead;
// Create the child stdin pipe.
VERIFY(::CreatePipe(&m_hStdIn, &hStdInWriteTmp, &sa, 0)); // Create the child stdout pipe.
VERIFY(::CreatePipe(&hStdOutReadTmp, &m_hStdOut, &sa, 0));
// Create the child stderr pipe.
VERIFY(::CreatePipe(&hStdErrReadTmp, &m_hStdErr, &sa, 0)); VERIFY(::DuplicateHandle(hProcess, hStdInWriteTmp,
hProcess, &m_hStdInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)); VERIFY(::DuplicateHandle(hProcess, hStdOutReadTmp,
hProcess, &m_hStdOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS)); VERIFY(::DuplicateHandle(hProcess, hStdErrReadTmp,
hProcess, &m_hStdErrRead, 0, FALSE, DUPLICATE_SAME_ACCESS)); // Close inheritable copies of the handles you do not want to be
// inherited. VERIFY(::CloseHandle(hStdInWriteTmp));
VERIFY(::CloseHandle(hStdOutReadTmp));
VERIFY(::CloseHandle(hStdErrReadTmp)); STARTUPINFO StartUpInfo = {0};
PROCESS_INFORMATION ProInfo = {0};
StartUpInfo.cb = sizeof( StartUpInfo );
StartUpInfo.wShowWindow = SW_HIDE; //want see consle set this SW_SHOW
StartUpInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
StartUpInfo.hStdOutput = m_hStdOut;
StartUpInfo.hStdInput = m_hStdIn;
StartUpInfo.hStdError = m_hStdErr;
BOOL bProOk = CreateProcess( NULL, "cmd",
NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL,
&StartUpInfo, &ProInfo );
if( !bProOk )
{
return;
}
// Close any unnecessary handles.
VERIFY(::CloseHandle(ProInfo.hThread));
WaitForInputIdle(ProInfo.hProcess,10000);
char szCmdLine[1024] = "dir\r\n";
// Write Command
ULONG uWrited = 0;
BOOL bWriteOk = WriteFile( m_hStdInWrite, szCmdLine, strlen(szCmdLine), &uWrited, NULL );
char szWrited[256] = {0};
sprintf( szWrited, "writed: %d", uWrited );
MessageBox( szWrited );
DWORD dwRead = 0;
CHAR chBuf[1024] = {0}; // Read output from the child process, and write to parent's STDOUT.
if( !ReadFile( m_hStdOutRead, chBuf, 1024, &dwRead,
NULL) || dwRead == 0)
{
TRACE("Read File Error!\n");
}
MessageBox( chBuf );
// Close Handle
VERIFY( CloseHandle( m_hStdOut ) );
VERIFY( CloseHandle( m_hStdIn ) );
VERIFY( CloseHandle( m_hStdErr ) );
VERIFY( CloseHandle( ProInfo.hProcess) );
VERIFY( CloseHandle( m_hStdInWrite ) );
VERIFY( CloseHandle( m_hStdOutRead ) );
VERIFY( CloseHandle( m_hStdErrRead ) );
return;
}