一、基本函数介绍
BOOL CreatePipe( //创建管道
PHANDLE hReadPipe, //管道读数据句柄
PHANDLE hWritePipe, //管道写数据句柄
PLSECURITY_ATTRIBUTES lpPipeAttributes, //安全属性,成员bInhertHandle表示子进程是否可继承
DWORD nSize //管道缓冲区大小,0代表默认缓冲区代销
)
安全属性结构体如下:
typedef struct _SECURITY_ATTRBUTES{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInhertHandle;
}SECURITY_ATTRBUTES,*PLSECURITY_ATTRIBUTES;
BOOL CreateProcess //创建进程
(
LPCTSTR lpApplicationName,//用来指定可执行模块的字符串
LPTSTR lpCommandLine,//该字符串指定要执行的命令行
LPSECURITY_ATTRIBUTES lpProcessAttributes,//安全属性,NULL表示默认
LPSECURITY_ATTRIBUTES lpThreadAttributes,//线程是否被继承.通常置为NULL
BOOL bInheritHandles,//新进程是否从调用进程处继承了句柄
DWORD dwCreationFlags,//指定附加的、用来控制优先类和进程的创建的标志
LPVOID lpEnvironment,//指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境
LPCTSTR lpCurrentDirectory,//这个字符串用来指定子进程的工作路径
LPSTARTUPINFO lpStartupInfo,//指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体
LPPROCESS_INFORMATIONlpProcessInformation//指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体
);
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
typedef struct_PROCESS_INFORMATION{
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
}PROCESS_INFORMATION;
二、匿名管道:只用于父子进程
创建匿名管道
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle = TRUE;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
{
MessageBox(L"创建匿名管道失败");
return;
}
STARTUPINFO sui;
ZeroMemory(&sui, sizeof(STARTUPINFO));
sui.cb = sizeof(STARTUPINFO);
sui.dwFlags = STARTF_USESTDHANDLES;
sui.hStdInput = hRead;
sui.hStdOutput = hWrite;
sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);
PROCESS_INFORMATION pi;
if (!CreateProcess(L"..\\Debug\\PipeChild.exe", NULL, NULL
, NULL, TRUE, 0, NULL, NULL, &sui, &pi))
{
CloseHandle(hRead);
CloseHandle(hWrite);
hRead = NULL;
hWrite = NULL;
CString strTips;
strTips.Format(L"%d", GetLastError());
MessageBox(L"创建子进程失败");
MessageBox(strTips);
return;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
读取数据
char szBuf[100] = { 0 };
DWORD dwRead;
if (!ReadFile(hRead, szBuf, 100, &dwRead, NULL))
{
MessageBox(L"读取数据失败");
return;
}
CString strData(szBuf);
MessageBox(strData);
写入数据
char szData[] = "parent:this is a test";
DWORD dwWrite;
if (!WriteFile(hWrite, szData, strlen(szData) + 1, &dwWrite, NULL))
{
MessageBox(L"写入数据失败");
return;
}
Tips:在子进程需要获取父进程创建时指定的管道操作句柄
三、命名管道
创建管道
hPipe = CreateNamedPipe(L"\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL);
if (INVALID_HANDLE_VALUE == hPipe)
{
MessageBox(L"创建命名管道失败");
hPipe = nullptr;
return;
}
//创建那么人工重置事件对象
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == hEvent)
{
MessageBox(L"创建事件对象失败");
CloseHandle(hPipe);
hPipe = nullptr;
return;
}
OVERLAPPED ovlap;
ZeroMemory(&ovlap, 0, sizeof(OVERLAPPED));
ovlap.hEvent = hEvent;
if (!ConnectNamedPipe(hPipe, &ovlap))
{
if (ERROR_IO_PENDING != GetLastError())
{
MessageBox(L"等待客户端连接失败");
CloseHandle(hPipe);
hPipe = nullptr;
CloseHandle(hEvent);
return;
}
}
if (WAIT_FAILED == WaitForSingleObject(hEvent, INFINITE))
{
MessageBox(L"等待对象失败");
CloseHandle(hPipe);
hPipe = nullptr;
CloseHandle(hEvent);
return;
}
CloseHandle(hEvent);
连接管道
if (!WaitNamedPipe(L"\\\\.\\pipe\\MyPipe", NMPWAIT_WAIT_FOREVER))
{
MessageBox(L"当前无可使用的命名管道");
return;
}
hPipe = CreateFile(L"\\\\.\\pipe\\MyPipe", GENERIC_READ
| GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hPipe)
{
MessageBox(L"打开命名管道失败");
hPipe = nullptr;
return;
}
管道读写和匿名管道保持一致