windows核心编程 内核对象,创建进程(CreateProcess),管道(CreatePipe)
windows核心编程 内核对象,创建进程(CreateProcess),管道(CreatePipe)
主进程创建子进程并运行Ping 命令
/*
主进程创建子进程并运行Ping 命令
*/
#include <Windows.h>
#include <tchar.h>
#include <strsafe.h>
#define GRS_USEPRINTF() TCHAR pBuf[1024] = {}
#define GRS_PRINTF(...) \
StringCchPrintf(pBuf,1024,__VA_ARGS__);\
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),pBuf,lstrlen(pBuf),NULL,NULL);
#define GRS_USEPRINTFA() CHAR pBufA[1024] = {}
#define GRS_PRINTFA(...) \
StringCchPrintfA(pBufA,1024,__VA_ARGS__);\
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),pBufA,lstrlenA(pBufA),NULL,NULL);
#define GRS_ALLOC(sz) HeapAlloc(GetProcessHeap(),0,sz)
#define GRS_CALLOC(sz) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz)
#define GRS_SAFEFREE(sz) if(NULL != p){HeapFree(GetProcessHeap(),0,p);p=NULL;}
//获取应用程序所在的路径
void GetAppPath(PTSTR pszPath)
{
DWORD dwLen = 0;
//获取当前进程已加载模块的文件的完整路径
dwLen = GetModuleFileName(NULL, pszPath, MAX_PATH);//NULL表示获取当前exe全路径
if (dwLen == 0) return;
for (DWORD i = dwLen; i > 0; i--)
{
if ('\\' == pszPath[i])
{
pszPath[i + 1] = '\0';
break;
}
}
}
int _tmain()
{
GRS_USEPRINTF();
TCHAR pszAppPath[MAX_PATH + 1] = {};
TCHAR pszExe[MAX_PATH + 1] = {};
GetAppPath(pszAppPath);//获取当前exe文件所在的目录
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi = {};
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
sa.bInheritHandle = FALSE;//该子进程不可继承
printf("这是父进程的控制台窗口!\r\n");
//重定向到管道,接受ping命令的输出
GRS_USEPRINTFA();
StringCchPrintf(pszExe, MAX_PATH, _T("PING www.baidu.com"));
BYTE pBuffer[1024] = {};//缓存
DWORD dwLen = 0;
HANDLE hRead1, hWrite1;//管道读写句柄
BOOL bRet;
sa.bInheritHandle = TRUE;
//创建匿名管道,管道句柄是可被继承的
bRet = CreatePipe(&hRead1, &hWrite1, &sa, 1024);
if (!bRet)
{
GRS_PRINTF(_T("管道创建失败,Error Code:%d\n"), GetLastError());
_tsystem(_T("PAUSE"));
return 0;
}
/**/
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;//隐藏子进程窗口
si.hStdOutput = hWrite1;//将子进程的输出输入通道
//创建子进程,ping命令,子进程是可继承的
CreateProcess(NULL, pszExe, NULL, NULL, TRUE,
DETACHED_PROCESS, NULL, pszAppPath, &si, &pi);
//管道句柄已被继承,本地则可关闭,否则管道内核对象没有释放,
// 之后的读管道操作人会一直等待管道吸入数据
// HANDLE pHandle = GetCurrentProcess();//0xfffffff
// HANDLE tHandle = GetCurrentThread();//0xfffffffe
//党ping指向完毕,已经没有数据写入,就会因ReadFile读不到数据,而进程阻塞
CloseHandle(hWrite1);
printf("执行子进程:运行ping命令!\r\n");
//读管道知道管道关闭
dwLen = 1000;
DWORD dwRead = 0;
while (ReadFile(hRead1,pBuffer,dwLen,&dwRead,NULL))
{
if (0 == dwRead)
{
break;
}
GRS_PRINTFA("%s\n", pBuffer);
ZeroMemory(pBuffer, 1024);
}
GRS_PRINTF(_T("Read Completion!\n\n"));
CloseHandle(hRead1);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
_tsystem(_T("PAUSE"));
return 0;
}