void CProgressDlg::OnCancel() { m_bAbort = true; if(m_bDone) { CResizableStandAloneDialog::OnCancel(); return; } if( g_Git.m_CurrentGitPi.hProcess ) { if(::GenerateConsoleCtrlEvent(CTRL_C_EVENT,0)) { ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000); } else { GetLastError(); } KillProcessTree(g_Git.m_CurrentGitPi.dwProcessId); } ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000); CResizableStandAloneDialog::OnCancel(); }
void CProgressDlg::KillProcessTree(DWORD dwProcessId) { // recursively kills a process tree // This is not optimized, but works and isn't called very often ;) PROCESSENTRY32 pe; memset(&pe, 0, sizeof(PROCESSENTRY32)); pe.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (::Process32First(hSnap, &pe)) { do { if (pe.th32ParentProcessID == dwProcessId) KillProcessTree(pe.th32ProcessID); } while (::Process32Next(hSnap, &pe)); HANDLE hProc = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); if (hProc) { ::TerminateProcess(hProc, 1); ::CloseHandle(hProc); } } ::CloseHandle(hSnap); }
void CProgressDlg::KillProcessTree(DWORD dwProcessId, unsigned int depth) { // recursively kills a process tree // This is not optimized, but works and isn't called very often ;) if (!dwProcessId || depth > 20) return; PROCESSENTRY32 pe; memset(&pe, 0, sizeof(PROCESSENTRY32)); pe.dwSize = sizeof(PROCESSENTRY32); CAutoGeneralHandle hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (::Process32First(hSnap, &pe)) { do { if (pe.th32ParentProcessID == dwProcessId) KillProcessTree(pe.th32ProcessID, depth + 1); } while (::Process32Next(hSnap, &pe)); CAutoGeneralHandle hProc = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); if (hProc) ::TerminateProcess(hProc, 1); } }
void CProgressDlg::OnCancel() { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": User canceled\n")); m_bAbort = true; if(m_bDone) { CResizableStandAloneDialog::OnCancel(); return; } if( m_Git->m_CurrentGitPi.hProcess ) { DWORD dwConfirmKillProcess = CRegDWORD(_T("Software\\TortoiseGit\\ConfirmKillProcess")); if (dwConfirmKillProcess && CMessageBox::Show(m_hWnd, IDS_PROC_CONFIRMKILLPROCESS, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION) != IDYES) return; if(::GenerateConsoleCtrlEvent(CTRL_C_EVENT,0)) { ::WaitForSingleObject(m_Git->m_CurrentGitPi.hProcess ,10000); } else { GetLastError(); } KillProcessTree(m_Git->m_CurrentGitPi.dwProcessId); } ::WaitForSingleObject(m_Git->m_CurrentGitPi.hProcess ,10000); CResizableStandAloneDialog::OnCancel(); }
// Helper // n.b. recursive void CServiceRunner::KillProcessTree(DWORD myprocID, DWORD dwTimeout) { PROCESSENTRY32 pe; memset(&pe, 0, sizeof(PROCESSENTRY32)); pe.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnap = :: CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (::Process32First(hSnap, &pe)) { BOOL bContinue = TRUE; // kill child processes while (bContinue) { if (pe.th32ParentProcessID == myprocID) { // Recurse KillProcessTree(pe.th32ProcessID, dwTimeout); } bContinue = ::Process32Next(hSnap, &pe); } // kill the main process HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID); if (hProc) { ::TerminateProcess(hProc, 1); ::CloseHandle(hProc); } } }
void CServiceRunner::KillProcess() { if (m_pid != 0) { KillProcessTree(m_pid, 0); m_processHandle = 0; m_pid = 0; } }
int CServiceRunner::Exit(unsigned long exitcode) { m_exiting = true; if (m_serviceHandler) { // Update service status m_status.dwCurrentState = SERVICE_STOP_PENDING; m_status.dwWaitHint = 3000; SetServiceStatus(m_serviceHandler, &m_status); } // Clean up. if (m_pid) { KillProcessTree(m_pid, 0); m_processHandle = 0; m_pid = 0; } if (m_serviceHandler) { m_status.dwCurrentState = SERVICE_STOPPED; if (exitcode) { m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; m_status.dwServiceSpecificExitCode = exitcode; } else { m_status.dwWin32ExitCode = NO_ERROR; m_status.dwServiceSpecificExitCode = 0; } SetServiceStatus(m_serviceHandler, &m_status); } WaitForSingleObject(m_monitorThreadHandle, INFINITE); return exitcode; }