Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Не работает безопасное завершение дочерних процессов на C++ (http://forum.oszone.net/showthread.php?t=316948)

Макс1 19-07-2016 20:16 2652291

Не работает безопасное завершение дочерних процессов на C++
 
Необходимо завершать процесс и все его дочерние процессы в программе на Microsoft Visual C++
Используется немного измененный код.
Функция SafeTerminateProcess для безопасного завершения процесса по этой ссылке.
http://hyacinth.byus.net/moniwiki/wi...rminateProcess
И функция KillProcessTree для рекурсивного завершения дочерних процессов по этой ссылке:
http://www.cyberforum.ru/cpp-builder/thread1202071.html
Если не удается завершить процесс с помощью функции SafeTerminateProcess, завершаю его с помощью функции TerminateProcess.
Завершение процессов работает, но для дочерних процессов отладка показывает, что в большинстве случаев не работает функция SafeTerminateProcess, и в результате вызывается функция TerminateProcess. Для основного процесса SafeTerminateProcess всегда работает.
Появляется одна из двух ошибок (если не было первой, в большинстве случаев появляется вторая).
Функция GetExitCodeProcess получает ExitCode для дочернего процесса, равный нулю.
Или бывает вторая ошибка hRT == null с ошибкой код 0x5 - Access Denied.
Если сделать следующий код, вместо нее появляется ошибка Error unknown revision 0x519

Код:

PSECURITY_DESCRIPTOR pSD;
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
                        SECURITY_DESCRIPTOR_MIN_LENGTH);
 
                SECURITY_ATTRIBUTES sa;
                sa.nLength = sizeof (SECURITY_ATTRIBUTES);
                sa.lpSecurityDescriptor = pSD;
                sa.bInheritHandle = TRUE;
 
hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess,
                        &sa,
                        0,
                        (LPTHREAD_START_ROUTINE)pfnExitProc,
                        (PVOID)uExitCode, 0, &dwTID);

Если делать несколько попыток заврешения того же процесса с помощью SafeTerminateProcess, это не помогает. Можно ли исправить эти 2 ошибки и сделать, чтобы функция SafeTerminateProcess всегда завершала дочерние процессы?


Код:

BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
        DWORD dwTID, dwCode, dwErr = 0;
        HANDLE hProcessDup = INVALID_HANDLE_VALUE;
        HANDLE hRT = NULL;
        HINSTANCE hKernel = GetModuleHandle(_T("kernel32"));
        BOOL bSuccess = FALSE;
        BOOL bDup = DuplicateHandle(GetCurrentProcess(),
                hProcess,
                GetCurrentProcess(),
                &hProcessDup,
                PROCESS_ALL_ACCESS,
                FALSE,
                0);
 
        if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && 
(dwCode == STILL_ACTIVE))
        {
                FARPROC pfnExitProc;
                pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
                hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess,
                        NULL,
                        0,
                        (LPTHREAD_START_ROUTINE)pfnExitProc,
                        (PVOID)uExitCode, 0, &dwTID);
 
                if (hRT == NULL) dwErr = GetLastError();
        }
        else
        {
                dwErr = ERROR_PROCESS_ABORTED;
        }
        if (hRT)
        {
                WaitForSingleObject((bDup) ? hProcessDup : hProcess, (DWORD)
10);
                CloseHandle(hRT);
                bSuccess = TRUE;
        }
        if (bDup)
                CloseHandle(hProcessDup);
        if (!bSuccess)
                SetLastError(dwErr);
        return bSuccess;
}
 
bool KillProcessTree(DWORD myprocID, DWORD dwTimeout)
{
        bool bRet = true;
        HANDLE hWnd;
        PROCESSENTRY32 pe;
 
        memset(&pe, 0, sizeof(PROCESSENTRY32));
        pe.dwSize = sizeof(PROCESSENTRY32);
 
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 
        if (Process32First(hSnap, &pe))
        {
                BOOL bContinue = TRUE;
 
                while (bContinue)
                {
                        if (pe.th32ParentProcessID == myprocID)
                        {
 
                                KillProcessTree(pe.th32ProcessID, dwTimeout);
 
                                HANDLE hChildProc = OpenProcess
(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
 
                                if (hChildProc)
                                {
 
                                        if (WaitForSingleObject(hChildProc, 
dwTimeout) == WAIT_OBJECT_0)
                                                bRet = true;
                                        else
                                        {       
                                                    bRet = 
SafeTerminateProcess(hChildProc, 0);
                                                if (!bRet)
                                                        bRet = 
TerminateProcess(hChildProc, 0);
                                        }
                                        CloseHandle(hChildProc);
                                }
                        }
                        bContinue = Process32Next(hSnap, &pe);
                }
 
                HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 
myprocID);
 
                if (hProc)
                {
                        if (!SafeTerminateProcess(hProc, 0))
                                TerminateProcess(hProc, 0);
                        CloseHandle(hProc);
                }
        }
        return bRet;
}



Время: 04:54.

Время: 04:54.
© OSzone.net 2001-