功能:
1.各个进程启动、挂起、恢复、停止等
2.监听进程的运行状态,进程退出(正常、非正常)时,通知用户
3.异步队列
4.线程安全
进程管理器类:
#ifndef __ProcessManager_ProcessManager_H__ #define __ProcessManager_ProcessManager_H__ #include "Process.h" #define PROCESSMANAGER_AUTO_MUTEX boost::recursive_mutex PROCESSMANAGER_AUTO_MUTEX_NAME; #define PROCESSMANAGER_LOCK_AUTO_MUTEX boost::recursive_mutex::scoped_lock AutoMutexLock(PROCESSMANAGER_AUTO_MUTEX_NAME); /** Process Manager */ class ProcessManager : public QObject, public Singleton<ProcessManager> { Q_OBJECT public: /** Default constructor. */ ProcessManager(Log* pLog); /** Default destructor. */ ~ProcessManager(void); public: /** start */ Process* Start(const string& strName, const string& strCmdLine, bool bShowWnd = true); /** suspend */ void Suspend(Process* pProc); /** resume */ void Resume(Process* pProc); /** stop */ void Stop(Process* pProc); /** suspend all */ void SuspendAll(); /** resume all */ void ResumeAll(); /** stop all */ void StopAll(); /** Override standard Singleton retrieval. */ static ProcessManager& GetSingleton(void); /** Override standard Singleton retrieval. */ static ProcessManager* GetSingletonPtr(void); protected slots: /** Notify finish */ void _NoifyFinished(Process* pProc); Q_SIGNALS: /** Fire finish */ void _FireFinished(const string&); private: typedef map<string, Process*> ProcessMap; ProcessMap m_Processs; Log* m_pLog; PROCESSMANAGER_AUTO_MUTEX }; #endif // __ProcessManager_ProcessManager_H__
#include "ProcessManager.h" //----------------------------------------------------------------------- template<> ProcessManager* Singleton<ProcessManager>::m_pSingleton = 0; ProcessManager* ProcessManager::GetSingletonPtr(void) { return m_pSingleton; } //----------------------------------------------------------------------- ProcessManager& ProcessManager::GetSingleton(void) { assert(m_pSingleton); return *m_pSingleton; } //----------------------------------------------------------------------- ProcessManager::ProcessManager(Log* pLog) { if (pLog == NULL) { THROW_EXCEPTION("Log can not be null!", "ProcessManager"); } m_pLog = pLog; } //----------------------------------------------------------------------- ProcessManager::~ProcessManager(void) { StopAll(); } //----------------------------------------------------------------------- Process* ProcessManager::Start( const string& strName, const string& strCmdLine, bool bShowWnd /*= true*/ ) { PROCESSMANAGER_LOCK_AUTO_MUTEX ProcessMap::iterator i = m_Processs.find(strName); if (i != m_Processs.end()) { return i->second; } else { Process* pProc = new Process(strName, m_pLog); connect(pProc, SIGNAL(_FireFinished(Process*)), this, SLOT(_NoifyFinished(Process*)), Qt::QueuedConnection); m_Processs[strName] = pProc; pProc->Start(strCmdLine, bShowWnd); return pProc; } } //----------------------------------------------------------------------- void ProcessManager::Suspend(Process* pProc) { PROCESSMANAGER_LOCK_AUTO_MUTEX pProc->Suspend(); } //----------------------------------------------------------------------- void ProcessManager::Resume(Process* pProc) { PROCESSMANAGER_LOCK_AUTO_MUTEX pProc->Resume(); } //----------------------------------------------------------------------- void ProcessManager::Stop(Process* pProc) { PROCESSMANAGER_LOCK_AUTO_MUTEX pProc->Stop(); } //----------------------------------------------------------------------- void ProcessManager::SuspendAll() { PROCESSMANAGER_LOCK_AUTO_MUTEX ProcessMap::iterator i = m_Processs.begin(); for ( ; i != m_Processs.end(); ++i) { i->second->Suspend(); } } //----------------------------------------------------------------------- void ProcessManager::ResumeAll() { PROCESSMANAGER_LOCK_AUTO_MUTEX ProcessMap::iterator i = m_Processs.begin(); for ( ; i != m_Processs.end(); ++i) { i->second->Resume(); } } //----------------------------------------------------------------------- void ProcessManager::StopAll() { PROCESSMANAGER_LOCK_AUTO_MUTEX ProcessMap::iterator i = m_Processs.begin(); for ( ; i != m_Processs.end(); ++i) { i->second->Stop(); } } //----------------------------------------------------------------------- void ProcessManager::_NoifyFinished(Process* pProc) { PROCESSMANAGER_LOCK_AUTO_MUTEX emit _FireFinished(pProc->GetName()); ProcessMap::iterator i = m_Processs.find(pProc->GetName()); if (i != m_Processs.end()) { m_Processs.erase(i); } delete pProc; }
进程类:
#ifndef __ProcessManager_Process_H__ #define __ProcessManager_Process_H__ #include "PreDefine.h" #define PROCESS_AUTO_MUTEX boost::recursive_mutex PROCESS_AUTO_MUTEX_NAME; #define PROCESS_LOCK_AUTO_MUTEX boost::recursive_mutex::scoped_lock AutoMutexLock(PROCESS_AUTO_MUTEX_NAME); /** Process */ class Process : public QObject { Q_OBJECT friend class ProcessManager; protected: /** Default constructor - used by ProcessManager. Warning Do not call directly */ Process(const string& strName, Log* pLog); /** Default destructor. */ ~Process(); public: /** start process */ bool Start(const string& strCmdLine, bool bShowWnd = true); /** suspend process */ void Suspend(); /** resume process */ void Resume(); /** stop process */ void Stop(); /** is process runing */ bool IsRuning(); /** get name */ string GetName(); private: /** listen to process is stoped ? */ void Listener(); Q_SIGNALS: /** Fire ProcessManager this process is stoped */ void _FireFinished(Process*); protected: /* Gets the last loading error */ string ProcessError(void); private: string m_strName; Log* m_pLog; HANDLE m_hPId; HANDLE m_hTId; boost::thread* m_pListener; PROCESS_AUTO_MUTEX }; #endif // __ProcessManager_Process_H__
#include "Process.h" //----------------------------------------------------------------------- Process::Process(const string& strName, Log* pLog) { if (pLog == NULL) { THROW_EXCEPTION("Log can not be null!", "Process"); } m_strName = strName; m_pLog = pLog; m_hPId = NULL; m_hTId = NULL; m_pListener = NULL; } //----------------------------------------------------------------------- Process::~Process() { } //----------------------------------------------------------------------- bool Process::Start(const string& strCmdLine, bool bShowWnd /** = true */) { PROCESS_LOCK_AUTO_MUTEX if (m_hPId != NULL) { //log m_pLog->LogMessage("Process " + m_strName + " is started.", LMT_OUTBAR); return true; } //-----------Create Process----------- STARTUPINFOA si; ZeroMemory(&si, sizeof(STARTUPINFOA)); si.cb = sizeof(STARTUPINFOA); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = bShowWnd ? SW_SHOW : SW_HIDE; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); BOOL bSuccess = CreateProcessA(NULL, (LPSTR)(strCmdLine.c_str()), NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); if (!bSuccess) { //log m_pLog->LogMessage("Could not start process " + m_strName + ". System Error: " + ProcessError(), LMT_OUTBAR); //notify process manager to remove me emit _FireFinished(this); return false; } //log m_pLog->LogMessage("Start process " + m_strName + " successful.", LMT_OUTBAR); m_hPId = pi.hProcess; m_hTId = pi.hThread; //-----------Listener----------- boost::function0<void> listenerFunc = boost::bind(&Process::Listener, this); m_pListener = new boost::thread(listenerFunc); //-----------Resume----------- ResumeThread(pi.hThread); WaitForInputIdle(pi.hProcess, 5000); return true; } //----------------------------------------------------------------------- void Process::Suspend() { PROCESS_LOCK_AUTO_MUTEX if (m_hPId == NULL) return; SuspendThread(m_hTId); } //----------------------------------------------------------------------- void Process::Resume() { PROCESS_LOCK_AUTO_MUTEX if (m_hPId == NULL) return; ResumeThread(m_hTId); } //----------------------------------------------------------------------- void Process::Stop() { PROCESS_LOCK_AUTO_MUTEX if (m_hPId == NULL) return; //Kill Listener m_pListener->interrupt(); m_pListener->detach(); delete m_pListener; m_pListener = NULL; //Kill Process TerminateProcess(m_hPId, 0); m_hPId = NULL; m_hTId = NULL; //log m_pLog->LogMessage("Process " + m_strName + " is stoped.", LMT_OUTBAR); //notify process manager to remove me emit _FireFinished(this); } //----------------------------------------------------------------------- bool Process::IsRuning() { PROCESS_LOCK_AUTO_MUTEX if (m_hPId == NULL) return false; return true; } //----------------------------------------------------------------------- string Process::GetName() { return m_strName; } //----------------------------------------------------------------------- void Process::Listener() { try { WaitForSingleObject(m_hPId, INFINITE); { //local : avoid to always lock PROCESS_LOCK_AUTO_MUTEX m_pListener->detach(); delete m_pListener; m_pListener = NULL; m_hPId = NULL; m_hTId = NULL; //log m_pLog->LogMessage("Process " + m_strName + " is stoped.", LMT_OUTBAR); //notify process manager to remove me emit _FireFinished(this); } } catch(const boost::thread_interrupted&) { //interrupted } catch(...) { //other } } string Process::ProcessError( void ) { LPVOID lpMsgBuf; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL); string strError = (char*)lpMsgBuf; LocalFree(lpMsgBuf); return strError; }