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


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

实现:

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

 

posted @ 2013-07-05 23:06  爱生活,爱编程  阅读(576)  评论(0编辑  收藏  举报