「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
启动一个进程:
如果我们有一个需求,需要在一个程序中启动另一个程序,就需要了解进程这个概念。执行一个程序,必然就产生一个进程。执行起来的App进程其实是shell调用CreateProcess激活的。所以在一个程序中启动另一个程序,就需要用到CreateProcess()。
函数原型:
CreateProcess(LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
实例:
CString strPath = "";//这里我会用全路径+文件名+扩展名
CString strEnvironment = "";//路径名
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
CreateProcess(NULL, CT2W(strPath), NULL, NULL, FALSE, 0, NULL, strEnvironment, &si, &pi );
第一个参数lpApplicationName指定一个可执行文件名;
第二个参数lpCommandLine指定欲传给新进程的命令行参数;如果指定第一个参数为NULL,系统就会以第二个参数的第一个“段落(token)”作为可执行文件名,如果没有指定扩展名,默认采用“.EXE”扩展名。如果没有指定路径,系统就会按照五个搜寻路径来寻找可执行文件。
这五个搜寻路径分别是:1.调用者的可执行文件所在目录;2.调用者的当前工作目录;3.Windows目录;4.Windows System目录;5.环境变量中的path所设定的各目录。
第三个参数和第四个参数分别指定“进程对象”、“线程对象”这两个核心对象的安全属性;
第五个参数(TRUE或FALSE)用来设定这些安全属性是否要被继承;
第六个参数可以是许多常数的组合,影响进程的建立过程,这些常数中比较常用的是CREATE_SUSPENDED,它会使得子进程产生之后,其主线程立刻被暂停执行;
第七个参数指定进程所使用的环境变量区。通常会让子进程继承父进程的环境变量,就需要指定为NULL;
第八个参数设定子进程的工作目录和工作驱动器,指定为NULL,子进程就会使用父进程的工作目录与工作驱动器;
第九个参数是一个指向STARTUPINFO结构的指针。可以用来设定窗口的标题、位置与大小;
第十个参数是一个指向PROCESS_INFORMATION结构的指针;
typedef struct _PROCESS_INFORMATION
{
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
}PROCESS_INFORMATION;
结束一个进程:
- 一个进程想结束自己,可以调用VOID ExitProcesss(UINT fuExitCode);
- 一个进程想结束另一个进程,可以调用BOOL TerminateProcess(HANDLE hProcess, UINT fuExitCode);
TerminateProcess并不被建议使用,不是因为它的权利太大,而是因为一般进程结束时,系统会通知该进程所开启的所有DLLs,但如果你用TerminateProcess结束一个进程,系统是不会通知其他开启的DLLs的。
很显然,只要你有某一个进程的handle(句柄),就可以结束它的生命。
但是一般在应用的过程中,我们通过CreateProcess启动一个进程后,会采用本机通信的方法使两个进程之间建立联系,在需要关闭另一个进程时,通过发送一个自定义消息,在另一个进程收到消息后自己执行关闭命令。