在启动外部进程的时候,我们需要知道进程是否已经运行,如果运行了,则不能重复启动进程了。因为外部进程是其他程序,不是我们能够控制的,所以这里不是单例模式能够解决的。我们只是启动一下外部进程,如何控制只有一个进程实例在运行呢?或者说,我们程序控制外部进程的运行,如何确保我们启动的进程只被启动一次,或者已经启动则关闭进程。
我们这里都写好了代码,用函数封装好了。根据任务管理器中文件名判断进程是否运行,运行则关闭进程,未运行则启动进程。关闭进程和启动进程都封装成函数了。
我们以mysqld.exe为例说明。下面是任务管理器的进程列表:
不过看到映像名称为mysqld.exe *32,那么*32算不算文件名的一部分呢?当然不算。*32是64位系统为了将32位进程区分开来,所以额外添加的显示的标志,并不是进程名的一部分。
所以,我们检测mysqld.exe就行了。检测后,返回的结果是真假,那么如果进一步处理呢?如果已经运行,很多时候我们可能需要关闭这个进程,所以我们要提供一个关闭进程的函数,如下:
关闭进程函数:
bool EndProcess(DWORD pid)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
return TerminateProcess(hProcess,0);
}
如果没有检测到进程,那么我们经常需要启动进程,所以启动进程的函数如下:
void StartProcess(wchar_t * path,bool silent)
{
const TCHAR szOperator[]=L"open";//打开操作,用来打开程序,文件
const TCHAR szParam[]=L"";//给相应的程序传递参数,可以不传
ShellExecute(NULL,szOperator,path,szParam,NULL,silent?SW_HIDE:SW_NORMAL);
}
这两个函数只需要包含windows.h头文件就可以了。最后一个就是检测进程是否运行的函数:
bool IsProcessRun(wchar_t * process_name,DWORD & pid)
{
HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//创建系统进程快照
PROCESSENTRY32 processListStr;
processListStr.dwSize = sizeof(PROCESSENTRY32);
bool bCopy = Process32First(Snapshot, &processListStr);//获取第一个进程
while(bCopy)
{
if(lstrcmp(processListStr.szExeFile,process_name)==0)
{
pid=processListStr.th32ProcessID;
return true;
}
bCopy = Process32Next(Snapshot, &processListStr); //继续查找下一个进程
}
CloseHandle(Snapshot);
return false;
}
检测进程是否运行用到了进程快照,所以需要包含头文件Tlhelp32.h。然后最后就是用在自己的代码中了。下面是main中使用的代码:
void main()
{
DWORD pid;
if(!IsProcessRun(L"mysqld.exe",pid))
StartProcess(L".\\Component\\mysql\\bin\\mysqld.exe",false);
else
EndProcess(pid);
system("pause");
}
检测进程是否存在是基于快照,里面涉及到的三个函数,请自行查阅MSDN。