开发一个简易的任务监控程序


需求:时刻监控任务列表,如果需要一直启动的程序未开启,则开启

实现:

1、枚举当前已经启动的进程、获取进程的ID和名称

	vector

  

    launchedProcess;

	HANDLE handle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//创建当前快照列表

	PROCESSENTRY32* info=new PROCESSENTRY32;//创建进程信息变量,用于保存信息

	info->dwSize=sizeof(PROCESSENTRY32);//设置块大小

	int i=0;

	if(Process32First(handle,info))//开始枚举进程

	{

		if(GetLastError()==ERROR_NO_MORE_FILES )

		{

			AfxMessageBox(_T("No More Process"));

		}

		else

		{

			CString id,file;

			id.Format(L"%d",info->th32ProcessID);//获取当前进程ID

			file.Format(L"%s",info->szExeFile);//获取当前进程名



			////TRACE(L"ID:%s,Name:%s",id,file);



			launchedProcess.push_back(file);



			if(!isExistInList(id,file))

			{

				m_list.InsertItem(i,id);//插入一个项目

				m_list.SetItemData(i,info->th32ProcessID);//设置项目值

				m_list.SetItemText(i,1,file);//设置名

				i++;

			}

			while(Process32Next(handle,info)!=FALSE)//继续获取进程

			{

				id.Format(L"%5d",info->th32ProcessID);

				file.Format(L"%s",info->szExeFile);



				launchedProcess.push_back(file);



				if(!isExistInList(id,file))

				{

					m_list.InsertItem(i,id);

					m_list.SetItemData(i,info->th32ProcessID);

					m_list.SetItemText(i,1,file);

					i++;

				}

			}

		}

	}

	delete info;//参考博文中未添加

	CloseHandle(handle);//关闭进程句柄

  

2、通过进程ID获取进程所对应的执行文件路径,需要实现逻辑设备名映射盘符的问题

 

HANDLE hProcess = NULL;  

	BOOL bSuccess = FALSE;  

	

	// 由于进程权限问题,有些进程是无法被OpenProcess的,如果将调用进程的权限  

	// 提到“调试”权限,则可能可以打开更多的进程  

	hProcess = OpenProcess(   

		PROCESS_QUERY_INFORMATION | PROCESS_VM_READ ,   

		FALSE, dwProcessId );  



	CString path(_T(""));

	do   

	{  

		if ( NULL == hProcess )  

		{  

			// 打开句柄失败,比如进程为0的进程  

			break;  

		}  

		

		// 用于保存文件路径,扩大一位,是为了保证不会有溢出  

		TCHAR szPath[_MAX_PATH + 1] = {0};  

		

		// 模块句柄  

		HMODULE hMod = NULL;  

		// 这个参数在这个函数中没用处,仅仅为了调用EnumProcessModules  

		DWORD cbNeeded = 0;  

		

#if 0		

		// 【注】此种方法Win7-64bit cmd.exe获取不到路径(同时勾选dbgview、chrome、beyondcompare、cmd)

		

		// 获取路径  

		// 因为这个函数只是要获得进程的Exe路径,因为Exe路径正好在返回的数据的  

		// 第一位,则不用去关心cbNeeded,hMod里即是Exe文件的句柄.  

		// If this function is called from a 32-bit application running on WOW64,   

		// it can only enumerate the modules of a 32-bit process.   

		// If the process is a 64-bit process,   

		// this function fails and the last error code is ERROR_PARTIAL_COPY (299).  

		if( FALSE == EnumProcessModules( hProcess, &hMod,   

			sizeof( hMod ), &cbNeeded ) )  

		{  

			break;

		}  

		

		// 通过模块句柄,获取模块所在的文件路径,此处即为进程路径。  

		// 传的Size为_MAX_PATH,而不是_MAX_PATH+1,是因为保证不会存在溢出问题  

		if ( 0 == GetModuleFileNameEx( hProcess, hMod, szPath, _MAX_PATH ) )  

		{  

			break;  

		}  

#endif



#if 1

		TCHAR szWinPath[_MAX_PATH + 1] = {0};



		//http://www.codeproject.com/Questions/282205/Get-Path-all-of-opened-Windows-WinAPI

		HINSTANCE hinstLib; 

		typedef DWORD (WINAPI *FPGetProcessImageFileName)(HANDLE,LPTSTR,DWORD); 

		FPGetProcessImageFileName fpGetProcessImageFileName = NULL; 

		

		// Get a handle to the DLL module.

		GetWindowsDirectory(szWinPath,sizeof(szWinPath));

		path.Format(L"%s\\SYSTEM32\\psapi.dll",szWinPath);

		

		////TRACE(L"path:%s",(LPCTSTR)path);



		hinstLib = ::LoadLibrary((LPCTSTR)path); 

		if (hinstLib != NULL) 

		{

#ifdef UNICODE

#define GetProcessImageFileNameStr  "GetProcessImageFileNameW"

#else

#define GetProcessImageFileNameStr  "GetProcessImageFileNameA"

#endif // !UNICODE



			//http://blog.163.com/danshiming@126/blog/static/109412748201141425648762/

			CString strFunName = _T(GetProcessImageFileNameStr);

			CStringA strFunNameA(strFunName);

			fpGetProcessImageFileName = (FPGetProcessImageFileName) ::GetProcAddress(hinstLib, strFunNameA); 

			

			// If the function address is valid, call the function.

			if (NULL != fpGetProcessImageFileName) 

			{

				//

				if(!fpGetProcessImageFileName(hProcess, szPath, _MAX_PATH))

					GetLastError();

			}

		}

		else

		{

			AfxMessageBox(_T("psapi.dll not found"));

		}

		// Free the DLL when you are done.

		::FreeLibrary(hinstLib);

#endif



#if 0

		if(!GetProcessImageFileName(hProcess, szPath, _MAX_PATH))  

		{  

			break;  

		}

#endif

		// 保存文件路径  

		path = szPath;

		// //TRACE(L"%s",(LPCTSTR)path);

		// 查找成功了  



#if 1

		CString deviceName(_T(""));

		int num=0;//第三次出现\的位置左边即为逻辑设备名

		//"\Device\HarddiskVolume2\Windows\System32\cmd.exe"

		for(int i=0;i<path.GetLength();i++)

		{

			if(path.GetAt(i)=='\\')

			{

				num++;

				if(num == 3)

				{

					deviceName.Empty();

					deviceName = path.Left(i);

					path = path.Right(path.GetLength()-i-1);



					////TRACE(L"logicVolume:%s,path:%s",logicVolume,path);

					break;

				}

			}

		}



		//TRACE(L"deviceName---%s",deviceName);



		std::map<CString, CString>::iterator iterator1;

		std::map<CString, CString>::iterator Enditerator1 = m_mapDevicePath.end();

		for(iterator1 = m_mapDevicePath.begin();iterator1 != Enditerator1; iterator1++)

		{

			//TRACE(L"iterator---%s",iterator1->first);

			CStringA left(iterator1->first);

			CStringA right(deviceName);

			//TRACE(L"left---%s",left);

			//TRACE(L"right---%s",right);

			if(!left.Compare(right))

			{

				//TRACE("helloworld");

			}

			if(!iterator1->first.Compare(deviceName))

			{

				//TRACE(L"iterator===%s",iterator1->first);

				//TRACE(L"m_mapDevicePath---%s",m_mapDevicePath[deviceName]);

				deviceName = iterator1->second;

				break;

			}

		}

		//TRACE(L"deviceName---%s",deviceName);

		path = deviceName + path;

		TRACE(L"path---%s",path);

		cstrPath = path;

		path.Empty();

#endif

/******

        //两种由逻辑设备名映射盘符的解决链接



		//http://bbs.csdn.net/topics/330144410

		//IoVolumeDeviceToDosName()//需要ddk驱动神马的,超级麻烦,驱动用的



		//vc6.0不支持,被迫迁移到vs8,一下超链接部分的代码可直接拷贝编译运行

		//http://msdn.microsoft.com/en-us/library/cc542456(v=VS.85).aspx

******/

		if(cstrPath.GetLength())

			bSuccess = TRUE;  

	} while( 0 );

	

	// 释放句柄  

	if ( NULL != hProcess )  

	{  

		CloseHandle( hProcess );  

		hProcess = NULL;  

	}  

	

3、开启进程

 

//http://blog.csdn.net/itjobtxq/article/details/6233455

			SHELLEXECUTEINFO ShExecInfo = {0};

			ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);

			ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;

			ShExecInfo.hwnd = NULL;

			ShExecInfo.lpVerb = NULL;

			ShExecInfo.lpFile = m_daemonModulePath[i];

			ShExecInfo.lpParameters =_T("");

			ShExecInfo.lpDirectory = NULL;

			ShExecInfo.nShow = SW_SHOW;

			ShExecInfo.hInstApp = NULL;

			ShellExecuteEx(&ShExecInfo);

			WaitForSingleObject(ShExecInfo.hProcess,100);



			launchedProcess.push_back(m_daemonModulePath[i]);

 

4、边边角角的需求:只启用一个实例;最小化时任务栏不显示,只在后台中运行;再点击exe的图标,激活后台进程显示主窗口

其中需求4的最后一个小需求在vs2008生成的执行文件里会失败

最终程序截图:

vc6.0                                                                                                              vs2008

开发一个简易的任务监控程序开发一个简易的任务监控程序

工程和可执行文件下载:http://download.csdn.net/detail/lonelyrains/5705883

 

你可能感兴趣的:(监控)