当我们在硬盘上打开一个exe文件,操作系统会把exe加载到我们的内存中,加载到内存中的exe文件就是一个进程。
首先,要打开一个进程,windows提供了3个API来供我们使用,第一个是WinExec,声明如下:
UINT WinExec(
LPCSTR lpCmdLine, // 进程名
UINT uCmdShow // 窗口的样式,如何显示
);
以上这个API现在基本已经没有用了,第二个是ShellExecute,这个用的也比较少,我们系统的菜单的运行窗口,底层就是调用了这个API,声明如下:
HINSTANCE ShellExecute(
HWND hwnd, //父窗口的句柄
LPCTSTR lpOperation, //指定动作,如open
LPCTSTR lpFile, //要打开的进程或文件
LPCTSTR lpParameters, //给打开的进程指定一些参数
LPCTSTR lpDirectory, //指定默认目录,若为NULL,则指定当前工作目录
INT nShowCmd //窗口的样式,如何显示
);
第三个是CreateProcess这个API,这个API用的最多,功能也最强大,声明如下:
BOOL CreateProcess(
LPCTSTR lpApplicationName, // 进程名,我一般把该参设为NULL,把名字在第二个参数一起指定
LPTSTR lpCommandLine, // 要执行的命令
LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全属性,一般为NULL
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性,一般为NULL
BOOL bInheritHandles, // 指定子进程是否从父进程继承句柄
DWORD dwCreationFlags, // 指定打开的进程的一些附加标志
LPVOID lpEnvironment, // 指定新的环境块
LPCTSTR lpCurrentDirectory, // 指定当前工作目录
LPSTARTUPINFO lpStartupInfo, // 指定一个STARTUPINFO结构体
LPPROCESS_INFORMATION lpProcessInformation // 指定一个PROCESS_INFORMATION结构体
);
上面这个API 的后两个参数,提到了两个结构体,第一个是STARTUPINFO,第二个是PROCESS_INFORMATION,声明如下:
typedef struct _STARTUPINFO {
DWORD cb; //该结构体的大小
LPTSTR lpReserved; //保留,必须为
LPTSTR lpDesktop; //用于标识启动应用程序所在的桌面的名字,一般为NULL
LPTSTR lpTitle; //用于设定控制台窗口的名称,一般为NULL
DWORD dwX; //指定应用程序窗口的X坐标
DWORD dwY; //指定应用程序窗口的Y坐标
DWORD dwXSize; //窗口的宽
DWORD dwYSize; //窗口的高
DWORD dwXCountChars; //指定子控制台的宽
DWORD dwYCountChars; //指定子控制台的高
DWORD dwFillAttribute; //指定子控制台的文本和背景颜色
DWORD dwFlags; //指定一些标志
WORD wShowWindow; //指定应用程序如何出现
WORD cbReserved2; //保留,必须为NULL
LPBYTE lpReserved2; //保留,必须为NULL
HANDLE hStdInput; //指定控制台的输入句柄
HANDLE hStdOutput; //指定控制台的输出句柄
HANDLE hStdError; //指定控制台的输出句柄
} STARTUPINFO, *LPSTARTUPINFO;
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess; //新进程的句柄
HANDLE hThread; //主线程的句柄
DWORD dwProcessId; //进程ID
DWORD dwThreadId; //线程ID
} PROCESS_INFORMATION;
下面再介绍两个API,一个是TerminateProcess,用于结束一个进程,声明如下:
BOOL TerminateProcess(
HANDLE hProcess, // 进程的句柄
UINT uExitCode // 退出码,随便给一个就行,一般用不到
);
还有一个是ResumeThread,用于恢复一个线程运行,声明如下:
DWORD ResumeThread(
HANDLE hThread // 线程句柄
);
下面是一个对上面这些API 运用的例子:
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; //隐藏显示
//打开一个计算器
WCHAR wszCmdLine[] = L"calc.exe";
BOOL ret = CreateProcess(NULL, wszCmdLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); //打开进程的时候,让进程挂起,不让它运行, CREATE_SUSPENDED就是用来干这个的
if (ret)
{
printf("Create process successed!\n");
//先让进程休息4s
Sleep(4000);
printf("resume process\n");
//4s后,让计算器运行起来
ResumeThread(pi.hThread);
//在休息2s
Sleep(2000);
//然后结束掉计算器
TerminateProcess(pi.hProcess, 1);
printf("kill process done\n");
}
else
{
printf("Create process failed\n");
}
return 0;
}