DragonNest/Server/ServerCommon/ProcessManager.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

585 lines
No EOL
14 KiB
C++

#include "stdafx.h"
#include "ProcessManager.h"
#if defined(_LAUNCHER) || defined(_ESM)
#ifdef _LAUNCHER
#include "LauncherSession.h"
#include "ServiceUtil.h"
#elif _ESM
#include "LauncherPatcherSession.h"
#endif
extern void TextOut(const TCHAR * format, ...);
#endif
#include "psapi.h"
CProcessManager::CProcessManager()
{
m_hThread = NULL;
m_bForceStop = false;
}
CProcessManager::~CProcessManager()
{
Stop();
}
CProcessManager * CProcessManager::GetInstance()
{
static CProcessManager s;
return &s;
}
void CProcessManager::Start()
{
DWORD threadid;
m_bForceStop = false;
m_hThread = CreateThread(NULL, 0, _threadmain, (void*)this, 0, &threadid);
}
void CProcessManager::Stop()
{
if (m_hThread != NULL)
{
m_bForceStop = true;
WaitForSingleObject(m_hThread, INFINITE);
ScopeLock <CSyncLock> sync(m_Sync);
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
DWORD dwExit;
BOOL bRet = GetExitCodeProcess((*ii).hProcess, &dwExit);
TerminateProcess((*ii).hProcess, bRet == TRUE ? dwExit : false);
CloseHandle((*ii).hProcess);
if ((*ii).hThread > 0)
CloseHandle((*ii).hThread);
}
m_WatchingItems.clear();
}
}
bool CProcessManager::AddManagingItem(int nID, const char * pszExcutePath, const char * pszExe, const char * pszCmdParam, const char * pszWorkingPath)
{
ScopeLock <CSyncLock> sync(m_Sync);
std::map <int, sProcessItem>::iterator ii = m_ManagingItems.find(nID);
if (ii == m_ManagingItems.end())
{
sProcessItem Item;
memset(&Item, 0, sizeof(sProcessItem));
Item.nID = nID;
if (pszExcutePath)
{
strcpy_s(Item.szExcutePath, pszExcutePath);
FolderCheckAndCreate(pszExcutePath);
}
strcpy_s(Item.szExeName, pszExe);
if (pszCmdParam)
strcpy_s(Item.szCmdParam, pszCmdParam);
if (pszWorkingPath)
strcpy_s(Item.szWorkingPath, pszWorkingPath);
Item.bRestartFlag = true;
std::pair<std::map <int, sProcessItem>::iterator, bool> Ret = m_ManagingItems.insert(std::make_pair(nID, Item));
if (Ret.second == false)
return false;
return true;
}
return false;
}
void CProcessManager::MakeWatchingProcess()
{
if (SnapShotProcessList())
{
ScopeLock <CSyncLock> sync(m_Sync);
std::map <int, sProcessItem>::iterator ii;
for (ii = m_ManagingItems.begin(); ii != m_ManagingItems.end(); ii++)
{
std::vector <sSnapShotItem>::iterator ih;
for (ih = m_SnapShotList.begin(); ih != m_SnapShotList.end(); ih++)
{
if (!stricmp((*ii).second.szExeName, (*ih).szProcessName))
{
HANDLE hProcess = GetProcessHandle((*ih).nProcessID);
AddWatchingProcessAsync(hProcess, 0, (*ih).nProcessID, (*ii).second.nID, (*ii).second.szExeName, 0);
}
}
}
}
else
_ASSERT_EXPR(0, L"!SnapShotProcessList()");
}
bool CProcessManager::RunProcess(int nID, bool bRestart/*=false*/)
{
ScopeLock <CSyncLock> sync(m_Sync);
if (IsWatchingProcessAsync(nID)) return true;
const sProcessItem * pItem = GetManagingItemAsync(nID);
if (pItem == NULL) return false;
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR command[4096];
TCHAR title[512];
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_NORMAL;
std::vector<std::string> tokens;
TokenizeA(pItem->szExeName, tokens, ".");
_stprintf_s(title, _T("%s_%d"), tokens[0].c_str(), nID);
si.lpTitle = title;
ZeroMemory( &pi, sizeof(pi) );
if (strlen(pItem->szExcutePath) > 0)
_stprintf_s(command, _T("\"%s\\%s\" %s"), pItem->szExcutePath, pItem->szExeName, pItem->szCmdParam);
else
_stprintf_s(command, _T("\"%s\" %s"), pItem->szExeName, pItem->szCmdParam);
if (!CreateProcess(NULL, // No module name (use command line).
command, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
#ifdef _ESM
NULL,
#else //#ifdef _ESM
strlen(pItem->szWorkingPath) > 0 ? pItem->szWorkingPath : NULL, // Use parent's starting directory.
#endif //#ifdef _ESM
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)
{
DWORD Ret = GetLastError();
#if defined(_LAUNCHER)
TextOut(_T("Execute Failed '%s %s' ErrCode%d"), pItem->szExeName, pItem->szCmdParam, Ret);
#endif
return false;
}
#if defined(_LAUNCHER)
TextOut(_T("Execute Success (%s %s):%d"), pItem->szExeName, pItem->szCmdParam, pItem->nID);
#endif
AddWatchingProcessAsync(pi.hProcess, pi.hThread, pi.dwProcessId, pItem->nID, pItem->szExeName, timeGetTime(), bRestart);
return true;
}
bool CProcessManager::Terminate(int nID)
{
{
ScopeLock <CSyncLock> sync(m_Sync);
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
if ((*ii).nID == nID)
{
DWORD dwExit;
BOOL bRet = GetExitCodeProcess((*ii).hProcess, &dwExit);
TerminateProcess((*ii).hProcess, bRet == TRUE ? dwExit : 0);
CloseHandle((*ii).hProcess);
if ((*ii).hThread > 0)
CloseHandle((*ii).hThread);
m_WatchingItems.erase(ii);
return true;
}
}
}
return true;
}
void CProcessManager::TerminateAll()
{
ScopeLock <CSyncLock> sync(m_Sync);
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
DWORD dwExit;
BOOL bRet = GetExitCodeProcess((*ii).hProcess, &dwExit);
TerminateProcess((*ii).hProcess, bRet == TRUE ? dwExit : false);
CloseHandle((*ii).hProcess);
if ((*ii).hThread > 0)
CloseHandle((*ii).hThread);
}
m_WatchingItems.clear();
}
bool CProcessManager::IsRunProcess(int nID)
{
ScopeLock <CSyncLock> sync(m_Sync);
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
if ((*ii).nID == nID)
return true;
}
return false;
}
bool CProcessManager::IsRunProcess(const char * szpProcessName)
{
ScopeLock <CSyncLock> sync(m_Sync);
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
if (!stricmp((*ii).szProcessName, szpProcessName))
return true;
}
return false;
}
bool CProcessManager::GetExeName(int nID, char * pszNameOut)
{
ScopeLock <CSyncLock> sync(m_Sync);
std::map <int, sProcessItem>::iterator ii = m_ManagingItems.find(nID);
if (ii != m_ManagingItems.end())
{
strcpy_s(pszNameOut, MAX_PATH, (*ii).second.szExeName);
return true;
}
return false;
}
bool CProcessManager::SnapShotProcessList()
{
m_Sync.Lock();
m_SnapShotList.clear();
m_Sync.UnLock();
HANDLE hProcessSnap = NULL;
bool bReturn = false;
PROCESSENTRY32 pe32 = {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return false;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
DWORD Code = 0;
DWORD dwPriorityClass;
do
{
HANDLE hProcess;
// Get the actual priority class.
hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
dwPriorityClass = GetPriorityClass (hProcess);
sSnapShotItem item;
memset(&item, 0, sizeof(sSnapShotItem));
_tcscpy_s(item.szProcessName, pe32.szExeFile);
item.nProcessID = pe32.th32ProcessID;
m_Sync.Lock();
m_SnapShotList.push_back(item);
m_Sync.UnLock();
CloseHandle(hProcess);
}
while (Process32Next(hProcessSnap, &pe32));
bReturn = true;
}
else
bReturn = false;
CloseHandle (hProcessSnap);
return bReturn;
}
bool CProcessManager::CheckOwnProcess()
{
int nCnt = 0;
DWORD nProcessID = GetCurrentProcessId();
TCHAR szName[MAX_PATH];
bool bRet = GetSnapshotProcessName(nProcessID, szName);
if (bRet)
{
int nCount = FindSnapShotProcessCount(szName);
if (nCount >= 2)
return true;
}
return false;
}
bool CProcessManager::GetSnapshotProcessName(DWORD nProcessID, TCHAR * pName)
{
ScopeLock <CSyncLock> sync(m_Sync);
std::vector <sSnapShotItem>::iterator ii;
for (ii = m_SnapShotList.begin(); ii != m_SnapShotList.end(); ii++)
{
if ((*ii).nProcessID == nProcessID)
{
_tcscpy_s(pName, MAX_PATH, (*ii).szProcessName);
return true;
}
}
return false;
}
int CProcessManager::FindSnapShotProcessCount(const TCHAR * szName)
{
ScopeLock <CSyncLock> sync(m_Sync);
int nCount = 0;
std::vector <sSnapShotItem>::iterator ii;
for (ii = m_SnapShotList.begin(); ii != m_SnapShotList.end(); ii++)
{
if (!_tcscmp((*ii).szProcessName, szName))
nCount++;
}
return nCount;
}
void CProcessManager::GetExutePath(const char * pExe, char * pExcutePath)
{
if (pExcutePath == NULL) return;
ScopeLock <CSyncLock> sync(m_Sync);
for (std::map <int, sProcessItem>::iterator ii = m_ManagingItems.begin(); ii != m_ManagingItems.end(); ii++)
{
if (!stricmp((*ii).second.szExeName, pExe))
{
if (strlen((*ii).second.szExcutePath) > 0)
strcpy_s(pExcutePath, 512, (*ii).second.szExcutePath);
return;
}
}
}
void CProcessManager::GetExutePath(char * pExcutePath)
{
if (pExcutePath == NULL) return;
ScopeLock <CSyncLock> sync(m_Sync);
for (std::map <int, sProcessItem>::iterator ii = m_ManagingItems.begin(); ii != m_ManagingItems.end(); ii++)
{
if (strlen((*ii).second.szExcutePath) > 0)
{
strcpy_s(pExcutePath, 512, (*ii).second.szExcutePath);
return;
}
}
}
const sProcessItem * CProcessManager::GetManagingItemAsync(int nID)
{
std::map <int, sProcessItem>::iterator ii = m_ManagingItems.find(nID);
if (ii != m_ManagingItems.end())
return &(*ii).second;
return NULL;
}
void CProcessManager::AddWatchingProcessAsync(HANDLE hProcess, HANDLE hThread, DWORD dwProcessID, int nID, const TCHAR * pExeName, ULONG nCreateTick, bool bRestart/*=false*/)
{
//Check
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
if ((*ii).dwProcessID == dwProcessID)
return;
}
sProcessInfo Item;
memset(&Item, 0, sizeof(sProcessInfo));
Item.hProcess = hProcess;
Item.hThread = hThread;
Item.dwProcessID = dwProcessID;
Item.nID = nID;
_tcscpy_s(Item.szProcessName, pExeName);
Item.nCreateTick = nCreateTick;
Item.bRestart = bRestart;
m_WatchingItems.push_back(Item);
}
bool CProcessManager::IsWatchingProcessAsync(int nID)
{
std::vector <sProcessInfo>::iterator ii;
for (ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
if ((*ii).nID == nID)
return true;
}
return false;
}
HANDLE CProcessManager::GetProcessHandle(DWORD nProcessID)
{
HANDLE hProcess = 0;
hProcess = ::OpenProcess(
PROCESS_ALL_ACCESS, // Specifies all possible access flags
FALSE,
nProcessID//pProcess->Get_ProcessId()
);
if( !hProcess )
return 0;
else
return hProcess;
}
DWORD WINAPI CProcessManager::_threadmain(void* param)
{
((CProcessManager*)param)->ThreadMain();
return 0;
}
void CProcessManager::ThreadMain()
{
HANDLE hList[MAXIMUM_WAIT_OBJECTS];
unsigned int i;
std::vector <sProcessInfo>::iterator ii;
sProcessInfo temp;
while(m_bForceStop == false)
{
m_Sync.Lock();
for(i = 0; i < m_WatchingItems.size(); i++)
hList[i] = m_WatchingItems[i].hProcess;
m_Sync.UnLock();
if (i > 0)
{
DWORD ret;
ret = WaitForMultipleObjects(i, hList, FALSE, 2*1000);
if (ret != WAIT_TIMEOUT)
{
m_Sync.Lock();
memset(&temp, 0, sizeof(sProcessInfo));
for(ii = m_WatchingItems.begin(); ii != m_WatchingItems.end(); ii++)
{
if ((*ii).hProcess == hList[ret - WAIT_OBJECT_0])
{
temp = (*ii);
if (temp.bRestart)
{
(*ii).bRestart = false;
continue;
}
m_WatchingItems.erase(ii);
CloseHandle(temp.hProcess);
if (temp.hThread > 0)
CloseHandle(temp.hThread);
#if defined(_LAUNCHER)
TextOut(_T("Application Crash! (%s):%d\n"), temp.szProcessName, temp.nID);
if (temp.nID != 0)
{
CLauncherSession::GetInstance()->SendCrashEvent(temp.nID);
}
#endif
break;
}
}
m_Sync.UnLock();
if (temp.nID > 0)
{
const sProcessItem * pItem = GetManagingItemAsync(temp.nID);
if (pItem)
{
if (pItem->bRestartFlag && (temp.nCreateTick > 0 && temp.nCreateTick + 5000 < timeGetTime()))
{
Sleep(3*1000);
RunProcess(temp.nID);
}
}
}
}
} else
{
Sleep(2*1000);
//CLauncherSession::GetInstance()->SendPing();
}
}
m_hThread = 0;
}
bool CProcessManager::RunByName (char* command)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
ZeroMemory( &pi, sizeof(pi) );
if (!CreateProcess(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
return false;
return true;
}
bool CProcessManager::TerminateByName (char* strProcessName)
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ))
return false;
cProcesses = cbNeeded / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
{
char szProcessName[MAX_PATH] = "unknown";
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, aProcesses[i] );
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
{
GetModuleBaseNameA( hProcess, hMod, szProcessName, sizeof(szProcessName) );
}
}
if(strcmp(szProcessName, strProcessName)==0)
{
HANDLE hSameProcess = NULL;
hSameProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, aProcesses[i]);
if(hSameProcess != NULL)
{
DWORD ExitCode = 0;
BOOL bRet = GetExitCodeProcess(hSameProcess, &ExitCode);
if (bRet == FALSE)
ExitCode = 0;
bRet = ::TerminateProcess(hSameProcess, ExitCode );
if( bRet )
{
::WaitForSingleObject(hSameProcess, INFINITE);
}
::CloseHandle(hSameProcess);
return true;
}
}
CloseHandle( hProcess );
}
return false;
}