Windows核心编程——进程的基本概念以及创建和退出
一、什么是进程
进程是资源分配的基本单位,也是独立运行的基本单位。通俗讲就是一段程序执行的过程。
进程由两部分构成,一部分指一个内核对象,操作系统用它来管理进程,也是系统保存进程统计信息的地方。
令一部分由地址空间构成,包括文本区、数据区、堆栈区。文本区存储处理器执行的代码,数据区存储变量和进程执行期间使用的的动态内存分配,堆栈区存储活动过程中调用的指令和本地变量
二、进程的三种基本状态
进程在运行过程中不断改变其运行状态,通常情况下,一个运行进程必须具有以下三种状态
1)就绪(Ready):当进程分配到除了CPU以外的所有的必要资源,只要处理器分配资源就能马上执行,这时的状态就称为就绪状态。
2)运行(Running):当进程已经获得处理器的资源分配,进程正在运行,此时的进程状态称为运行状态
3)阻塞(Blockjer):正在执行的进程,由于等待某个事件发生而无法执行时,便放弃资源分配而处于阻塞状态,例如等待I/O完成,申请缓冲区不能满足,等待信号等。
三、进程的创建和退出
Windows下常见创建进程的方法:
1)Winexec
2)ShellExcute
3)CreateProcess
1.Winexec
UINT WinExec( LPCSTR lpCmdLine, // 路径名(可以带cmd命令行) UINT uCmdShow // 显示状态);
PS:如果lpCmdLine参数中可执行文件的名称不包含目录路径,则系统将按以下顺序搜索可执行文件的路径:
1.加载应用程序的目录。
2.当前目录。
3.Windows系统目录。GetSystemDirectory函数检索此目录的路径。
4.Windows目录。GetWindowsDirectory函数检索此目录的路径。
5.PATH环境变量中列出的目录。
示例:
在对话框添加一个测试按钮,添加事件:
打开一个进程:
UINT nRet = ::WinExec( "C:\\Users\\shadow\\Desktop\\depends.exe", // 路径名 SW_SHOW // 显示状态 );
还可以打开cmd(包括带参启动):
带参启动cmd:
/k 并显示控制台窗口
/c 执行命令并关闭控制台窗口
打开注册表:
UINT nRet = ::WinExec("cmd.exe /c regedit", SW_SHOW);
改uac权限:
UINT nRet = ::WinExec("cmd /k %windir%\\System32\\reg.exe ADD HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v EnableLUA /t REG_DWORD /d 0 /f",SW_SHOW);
2.ShellExcute
API函数:
HINSTANCE ShellExecute( HWND hwnd, //指定窗口的句柄 LPCTSTR lpOperation, //指定要进行的操作 LPCTSTR lpFile, LPCTSTR lpParameters, //若lpFile是可执行文件,则此参数指定命令行参数 LPCTSTR lpDirectory, //指定默认目录 INT nShowCmd //指定程序窗口初始化显示方式 );
示例:
ShellExecute(NULL, "open","C:\\Users\\shadow\\Desktop\\depends.exe",NULL, NULL,SW_SHOWNORMAL);
//打开进程 ShellExecute(NULL, "open", "www.baidu.com/s?wd=\"拼音\"", NULL, NULL,SW_SHOW); //打开网址 ShellExecute(NULL, "explore", "D:\\360", NULL, NULL, SW_SHOWNORMAL); //打开文件夹 ShellExecute(NULL, "print", "C:\\Users\\shadow\\Desktop\\t.txt", NULL, NULL, SW_HIDE);
//打印机 ShellExecute(NULL, "open", "cmd.exe", "/k dir", NULL, SW_SHOWNORMAL); //自动搜索路径
打开exe:
STARTUPINFO si = { 0 }; si.cb = sizeof(si); PROCESS_INFORMATION pi = { 0 }; TCHAR szCmdLine[] = {L"cmd.exe /k ping www.baidu.com"}; BOOL bRet = ::CreateProcess( NULL, //exe的路径 szCmdLine, //命令行参数 NULL, NULL, FALSE, 0, //没有别的需求,创建标志填0 NULL, //环境块 NULL, //当前目录 &si, //启动进程一些配置 &pi);
3.CreateProcess
API函数:
BOOL CreateProcess ( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
参数详解:https://blog.csdn.net/baidu_29198395/article/detai
ls/82926348
示例:
void CProcessDlg::OnBnClickedButton3() { STARTUPINFO si = { 0 }; si.cb = sizeof(si); PROCESS_INFORMATION pi = { 0 }; BOOL bRet = ::CreateProcess( "C:\\Users\\shadow\\Desktop\\depends.exe", NULL, //命令行参数 NULL, NULL, FALSE, 0, //没有别的需求,创建标志填0 NULL, //环境块 NULL, //当前目录 &si, //启动进程一些配置 &pi ); if (!bRet) { AfxMessageBox(_T("进程启动失败, 请调试")); } }
注意:
lpStartupInfo
cb
必须初始化为sizeof(STARTUPINFO),或sizeof*STARTUOINFOEX
四.退出进程
1) ExitProcess(0);
执行后直接退出进程,后边代码将无法执行
2)TerminateProcess (不推荐使用,因为目标进程没有机会清理资源)
3)进程中的所有线程自行终止运行(这种情况几乎从未发生)
4) 主线程的进入点函数返回(最好使用这个方法),main函数返回