代码环境:
- Windows10
- Dev-C++ 5.6.3
1. 创建进程
大体过程:process 进程 创建一个 child 进程
1.1 process.cpp
//process.cpp
#include <cstdio>
#include <windows.h>
DWORD CreateChildProcess(LPSTR szChildProcessCmd)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
// 清零进程信息
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
if(!CreateProcess(NULL, //使用命令行
szChildProcessCmd, //命令行
NULL, //不继承进程句柄
NULL, //不继承线程句柄
FALSE, //不继承句柄
0, //没有创建标志
NULL, //使用父进程环境变量
NULL, //使用父进程目录作为当前目录
&si, //STARTUPINFO结构
&pi) //PROCESS_INFORMATION 保存相关信息)
)
{
//创建失败
printf("CreateProcess failed (%d).\n",GetLastError());
return 1;
}
//创建成功后,父进程可以退出,在这里等待子进程执行结束
//通过 PROCESS_INFORMATION 返回的相关信息,hProcess 为子进程句柄
WaitForSingleObject(pi.hProcess, INFINITE);
//关闭进程句柄和线程句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
int main(int argc, char **argv){
CreateChildProcess("child.exe abc 123");
return 0;
}
1.2 child.cpp
//child.cpp
#include <windows.h>
#include <cstdio>
//#pragma comment(lib, "user32.lib")
/*
HeapAlloc 函数在进程的堆中分配指定大小的内存块,
并返回一个指向该内存块起始位置的指针。
*/
#define MyAlloc(size) HeapAlloc(GetProcessHeap(),0,size)
#define MyFree(lpMem) HeapFree(GetProcessHeap(),0,lpMem)
typedef struct _PROCESS_INFO
{
DWORD dwPid;
HANDLE hProcess;
DWORD dwPrioClass;
DWORD dwHandleCount;
DWORD dwAffinityMask;
SIZE_T dwWorkingSetSizeMax;
SIZE_T dwWorkingSetSizeMin;
LPWSTR szwCommandLine;
STARTUPINFO sti;
}PROCESS_INFO, *LPPROCESS_INFO;
//全局变量
HANDLE hMySelf;
//函数声明
DWORD GetProcessInfo(LPPROCESS_INFO lppi);
/*********************************
* winMain
* 功能:演示获取进程信息,在进程中获取命令行参数等
**********************************/
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
PROCESS_INFO pi;
INT argc;
WCHAR **argv;
DWORD i;
DWORD dwBufferSize = lstrlen(lpCmdLine) + MAX_PATH + 1024;
LPSTR szShowBuffer = reinterpret_cast<LPSTR>(MyAlloc(dwBufferSize));
hMySelf = hInstance;
//显示直接从WinMain 函数参数得到的消息
wsprintf(szShowBuffer,
"启动参数\n实例句柄:%.8X,命令行参数:%s,显示选项:%.8X",
hInstance, lpCmdLine, nCmdShow);
MessageBox(NULL,szShowBuffer, "WinMain 函数参数",MB_OK);
//使用自定义的函数获取相关信息
GetProcessInfo(&pi);
//将参数命令参数分离
argv = CommandLineToArgvW(pi.szwCommandLine,&argc);
// 字符处理,并显示
*szShowBuffer = NULL;
for(int i = 0; i < argc; ++i){
DWORD dwBufferSize = lstrlenW(*argv)+1;
LPSTR szMBArgv = reinterpret_cast<LPSTR>(MyAlloc(dwBufferSize));
WideCharToMultiByte(CP_ACP,NULL,*argv,-1,szMBArgv,dwBufferSize,NULL,NULL);
argv++;
lstrcat(szShowBuffer, "\n");
lstrcat(szShowBuffer, szMBArgv);
MyFree(szMBArgv);
}
MessageBox(NULL, szShowBuffer,"参数", MB_OK);
MyFree(szShowBuffer);
//打印其他信息 TODO
return 0;
}
/********************************
功能:获取进程相关信息,保存在Process_info_lppi中
参数:LPPROCESS_INFO lppi 用于保存相关信息
*********************************/
DWORD GetProcessInfo(LPPROCESS_INFO lppi)
{
//PID
lppi->dwPid = GetCurrentProcessId();
//句柄
lppi->hProcess = GetCurrentProcess();
//优先级
lppi->dwPrioClass = GetPriorityClass(hMySelf);
//句柄记数
lppi->dwHandleCount = GetProcessHandleCount(lppi->hProcess, &lppi->dwHandleCount);
//AffinityMask
/***
这个函数用于获取指定进程的处理器亲和性掩码,
即指示该进程可以在哪些处理器上运行
掩码存放于 lppi->dwAffinityMask中
**/
GetProcessAffinityMask(hMySelf,
reinterpret_cast<PDWORD_PTR>(&lppi->dwAffinityMask),
NULL);
//WorkingSetSize
/***
这个函数用于获取指定进程的工作集大小,
即进程当前使用的物理内存范围。
Min 和 Max
分别是用来存储最小工作集大小
和最大工作集大小的变量的地址。
*/
GetProcessWorkingSetSize(hMySelf,
&lppi->dwWorkingSetSizeMin,
&lppi->dwWorkingSetSizeMax);
lppi->szwCommandLine = GetCommandLineW();
//启动信息
/**
这个函数用于检索当前进程的启动信息,
包括启动窗口的位置、大小、标题和其他相关信息。
*/
GetStartupInfo(&lppi->sti);
return 0;
}
1.3 运行 process.exe
当然,在此之前把 编译好的 process.exe 和 编译好的 child.exe 放在同一个文件夹下
这个是 process 进程 创建的 child 进程中的MessageBox 显示的。
点击确认后,显示 child 中的第二个 MessageBox,其中的参数是 process 创建时传入的。
1.4 直接运行 child.exe