CreateProcess Redirect Pipe

#ifndef REDIRECT_H_INCLUDED__
#define REDIRECT_H_INCLUDED__

class CRedirect
{
public:

//--------------------------------------------------------------------------
// constructor
//--------------------------------------------------------------------------
CRedirect
(
LPCTSTR szCurrentDirectory = NULL
);

//--------------------------------------------------------------------------
// destructor
//--------------------------------------------------------------------------
virtual ~CRedirect();

//--------------------------------------------------------------------------
// public member functions
//--------------------------------------------------------------------------
virtual void Run(LPCTSTR szCommand);
virtual void Stop();
virtual CString GetOutPutString(){ return m_sOutput; }

protected:

//--------------------------------------------------------------------------
// member functions
//--------------------------------------------------------------------------
void AppendText(LPCTSTR Text);
void PeekAndPump();
void SetSleepInterval(DWORD dwMilliseconds);
void ShowLastError(LPCTSTR szText);

//--------------------------------------------------------------------------
// member data
//--------------------------------------------------------------------------
bool m_bStopped;
DWORD m_dwSleepMilliseconds;
CString m_sOutput;
LPCTSTR m_szCurrentDirectory;

};

#endif // REDIRECT_H_INCLUDED__

//------------------------------------------------------------------------------
// Redirect.cpp : implementation file
//
// Creates a child process that runs a user-specified command and redirects its
// standard output and standard error to a CEdit control.
//
// Written by Matt Brunk ([email protected])
// Copyright (C) 1999 Matt Brunk
// All rights reserved.
//
// This code may be used in compiled form in any way. This file may be
// distributed by any means providing it is not sold for profit without
// the written consent of the author, and providing that this notice and the
// author‘s name is included in the distribution. If the compiled form of the
// source code in this file is used in a commercial application, an e-mail to
// the author would be appreciated.
//
// Thanks to Dima Shamroni ([email protected]) for providing the essential
// code for this class.
//
// Thanks to Chris Maunder ([email protected]) for the PeekAndPump()
// function (from his CProgressWnd class).
//
// Initial Release Feb 8, 1999
//------------------------------------------------------------------------------

#include "stdafx.h"
#include <string.h>
#include "Redirect.h"

const int BUF_SIZE = 8192;

CRedirect::CRedirect
(
LPCTSTR szCurrentDirectory
)
{
m_bStopped = false;
m_dwSleepMilliseconds = 100;
m_szCurrentDirectory = szCurrentDirectory;
}

CRedirect::~CRedirect()
{
}

void CRedirect::Run(LPCTSTR szCommand)
{
HANDLE PipeReadHandle;
HANDLE PipeWriteHandle;
PROCESS_INFORMATION ProcessInfo;
SECURITY_ATTRIBUTES SecurityAttributes;
STARTUPINFO StartupInfo;
BOOL Success;

//--------------------------------------------------------------------------
// Zero the structures.
//--------------------------------------------------------------------------
ZeroMemory( &StartupInfo, sizeof( StartupInfo ));
ZeroMemory( &ProcessInfo, sizeof( ProcessInfo ));
ZeroMemory( &SecurityAttributes, sizeof( SecurityAttributes ));

//--------------------------------------------------------------------------
// Create a pipe for the child‘s STDOUT.
//--------------------------------------------------------------------------
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.bInheritHandle = TRUE;
SecurityAttributes.lpSecurityDescriptor = NULL;

Success = CreatePipe
(
&PipeReadHandle, // address of variable for read handle
&PipeWriteHandle, // address of variable for write handle
&SecurityAttributes, // pointer to security attributes
0 // number of bytes reserved for pipe (use default size)
);

if ( !Success )
{
ShowLastError(_T("Error creating pipe"));
return;
}

//--------------------------------------------------------------------------
// Set up members of STARTUPINFO structure.
//--------------------------------------------------------------------------
StartupInfo.cb = sizeof(STARTUPINFO);
StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
StartupInfo.wShowWindow = SW_HIDE;
StartupInfo.hStdOutput = PipeWriteHandle;
StartupInfo.hStdError = PipeWriteHandle;

//----------------------------------------------------------------------------
// Create the child process.
//----------------------------------------------------------------------------
Success = CreateProcess
(
NULL, // pointer to name of executable module
LPTSTR(szCommand), // command line
NULL, // pointer to process security attributes
NULL, // pointer to thread security attributes (use primary thread security attributes)
TRUE, // inherit handles
0, // creation flags
NULL, // pointer to new environment block (use parent‘s)
m_szCurrentDirectory, // pointer to current directory name
&StartupInfo, // pointer to STARTUPINFO
&ProcessInfo // pointer to PROCESS_INFORMATION
);

if ( !Success )
{
ShowLastError(_T("Error creating process"));
return;
}

DWORD BytesLeftThisMessage = 0;
DWORD NumBytesRead;
TCHAR PipeData[BUF_SIZE];
DWORD TotalBytesAvailable = 0;

for ( ; ; )
{
NumBytesRead = 0;

Success = PeekNamedPipe
(
PipeReadHandle, // handle to pipe to copy from
PipeData, // pointer to data buffer
1, // size, in bytes, of data buffer
&NumBytesRead, // pointer to number of bytes read
&TotalBytesAvailable, // pointer to total number of bytes available
&BytesLeftThisMessage // pointer to unread bytes in this message
);

if ( !Success )
{
ShowLastError(_T("PeekNamedPipe fialed"));
break;
}

if ( NumBytesRead )
{
Success = ReadFile
(
PipeReadHandle, // handle to pipe to copy from
PipeData, // address of buffer that receives data
BUF_SIZE - 1, // number of bytes to read
&NumBytesRead, // address of number of bytes read
NULL // address of structure for data for overlapped I/O
);

if ( !Success )
{
ShowLastError(_T("ReadFile fialed"));
break;
}

//------------------------------------------------------------------
// Zero-terminate the data.
//------------------------------------------------------------------
PipeData[NumBytesRead] = ‘\0‘;

//------------------------------------------------------------------
// Replace backspaces with spaces.
//------------------------------------------------------------------
for ( DWORD ii = 0; ii < NumBytesRead; ii++ )
{
if ( PipeData[ii] == _T(‘\b‘) )
{
PipeData[ii] = ‘ ‘;
}
}

//------------------------------------------------------------------
// If we‘re running a batch file that contains a pause command,
// assume it is the last output from the batch file and remove it.
//------------------------------------------------------------------
TCHAR *ptr = _tcsstr(PipeData, _T("Press any key to continue . . ."));
if ( ptr )
{
*ptr = ‘\0‘;
}

//------------------------------------------------------------------
// Append the output to the CEdit control.
//------------------------------------------------------------------
AppendText(PipeData);

//------------------------------------------------------------------
// Peek and pump messages.
//------------------------------------------------------------------
PeekAndPump();
}
else
{
//------------------------------------------------------------------
// If the child process has completed, break out.
//------------------------------------------------------------------
if ( WaitForSingleObject(ProcessInfo.hProcess, 0) == WAIT_OBJECT_0 ) //lint !e1924 (warning about C-style cast)
{
break;
}

//------------------------------------------------------------------
// Peek and pump messages.
//------------------------------------------------------------------
PeekAndPump();

//------------------------------------------------------------------
// If the user cancelled the operation, terminate the process.
//------------------------------------------------------------------
if ( m_bStopped )
{
Success = TerminateProcess
(
ProcessInfo.hProcess,
0
);

if ( Success )
{
AppendText(_T("\r\nCancelled.\r\n\r\nProcess terminated successfully.\r\n"));
}
else
{
ShowLastError(_T("Error terminating process."));
}

break;
}

//------------------------------------------------------------------
// Sleep.
//------------------------------------------------------------------
Sleep(m_dwSleepMilliseconds);
}

}

//--------------------------------------------------------------------------
// Close handles.
//--------------------------------------------------------------------------
Success = CloseHandle(ProcessInfo.hThread);
if ( !Success )
{
ShowLastError(_T("Error closing thread handle."));
}

Success = CloseHandle(ProcessInfo.hProcess);
if ( !Success )
{
ShowLastError(_T("Error closing process handle."));
}

Success = CloseHandle(PipeReadHandle);
if ( !Success )
{
ShowLastError(_T("Error closing pipe read handle."));
}

Success = CloseHandle(PipeWriteHandle);
if ( !Success )
{
ShowLastError(_T("Error closing pipe write handle."));
}

}

void CRedirect::ShowLastError(LPCTSTR szText)
{
LPVOID lpMsgBuf;
DWORD Success;

//--------------------------------------------------------------------------
// Get the system error message.
//--------------------------------------------------------------------------
Success = FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //lint !e1924 (warning about C-style cast)
LPTSTR(&lpMsgBuf),
0,
NULL
);

CString Msg;

Msg = szText;
Msg += _T("\r\n");
if ( Success )
{
Msg += LPTSTR(lpMsgBuf);
}
else
{
Msg += _T("No status because FormatMessage failed.\r\n");
}

AppendText(Msg);

}

void CRedirect::PeekAndPump()
{
MSG Msg;
while (::PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE))
{
(void)AfxGetApp()->PumpMessage(); //lint !e1924 (warning about C-style cast)
}
}

void CRedirect::Stop()
{
m_bStopped = true;
}

void CRedirect::AppendText(LPCTSTR Text)
{
m_sOutput = Text;
}

void CRedirect::SetSleepInterval(DWORD dwMilliseconds)
{
m_dwSleepMilliseconds = dwMilliseconds;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Useage Example

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CString command_line = _T("xxx.dat 或 xxx.exe");
CRedirect * pRedirect = new CRedirect();
pRedirect->Run((LPTSTR)(LPCTSTR)command_line);
CString sOutput = pRedirect->GetOutPutString();

时间: 2024-10-12 16:10:25

CreateProcess Redirect Pipe的相关文章

Redirect

In this lesson we are going to unleash what may be the coolest feature of the command line.It's called I/O redirection.The "I/O" stands for input/output and with this facility you can redirect the input and output of commands to and from files,a

Python的问题解决: IOError: [Errno 32] Broken pipe

遇到一个很奇怪的问题, web.py代码里面报错IOError: [Errno 32] Broken pipe 启动命令: nohup python xxx.py > xxx.log & ssh登录到机器上, 启动, 不会出现远程ssh执行启动脚本, 就会出现IOError问题 查看进程pid, ll /proc/<pid>/fd 发现, stderr也就是fd为2的文件, 竟然是个pipe, 是个broken pipe, 错误的地方找到了 猜测可能是ssh登录过去, nohup

管道(Pipe)/createPipe

BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针 PHANDLE hWritePipe, // 指向写句柄的指针 LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针 DWORD nSize // 管道大小); 管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道server,连接到一个管道的进程为管道客户机.一个进程在向管道写入数据后,还有一进程就能够从管道的还有一端将其读取出

linux c redirect 重定向

用execvp实现时,运行adb,如果adb 服务没有启动,会启动adb服务,启动adb服务时,pipe返回的管道在读的时候堵塞了. 查看了popen的源码,发现popen是用sh -c来执行的,避免了这个问题 不知道sh -c做了些什么操作,使得popen可以避免这个问题 代码如下: 1 #ifndef __RG_REDIRECT_H 2 #define __RG_REDIRECT_H 3 4 5 //#ifdef _LINUX //for linux version 6 7 #include

SpringMVC中redirect跳转后如何保存Model中的数据?

@RequestMapping(value = "delete-user", method = RequestMethod.POST) public String deleteUser(Long[] userId, RedirectAttributes modelMap) { userService.deleteUser(userId); modelMap.addFlashAttribute("resultMsg", "删除成功"); retur

Nginx学习笔记15rewrite之(二)redirect临时重定向

redirect标志跟permanent标志的区别是:redirect使用HTTP 302临时重定向,permanent使用HTTP 301永久重定向.本文介绍redirect标志的临时重定向动作. Nginx配置: location ~ ^/app2/ { rewrite ^/app2/(.*)$  /app/$1  redirect; } 运行结果: curl -v   http://ng.coe2coe.me:8000/app2/ * Hostname was NOT found in D

Java NIO (五) 管道 (Pipe)

Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 如下图: 向管道写数据: 从管道读数据: 1. 从读取管道的数据,需要访问source通道. 2. 调用source通道的read()方法来读取数据

Server.Transfer和Response.Redirect区别

根本上,Response是叫浏览器去重新转向到指定的网页,而Server自然是发生在服务器端为主了,因此会有以下区别: 1. Server.Transfer只能够转跳到本地虚拟目录指定的页面,而Response.Redirect则十分灵活:2. Server.Transfer可以将页面参数方便传递到指定页面:3. 使用时,Server.Transfer跳到别的页面后,浏览器显示的地址不会改变,有时反而会造成误会,当然也有些场合需要这样的效果:4. Server.Transfer可以减少客户端对服

linux下,pipe的容量的讨论与查看

1.pipe的容量 2.6标准版本的linux内核,pipe缓冲区是64KB,尽管命令ulimit -a看到管道大小8块,缓冲区的大小不是4 k,因为内核动态分配最大16"缓冲条目",乘64 k.这些限制是硬编码的 2.如何查看自己pc上的pipe多大 1)通过ulimit -a查看到 pipe size 一次原子写入为:512Bytes*8=4096Bytes 查看缓冲条目个数:cat /usr/src/kernels/3.10.0-327.el7.x86_64/include/li