ERROR_INVALID_HANDLE в TerminateProcess (VS C ++) - PullRequest
4 голосов
/ 14 января 2011

Отказ от ответственности: это часть требований программы, поэтому она не предназначена для чего-то плохого.Не стесняйтесь указывать на любое неправильное использование, если вы обнаружите один.Я новичок в C ++.

По сути, я пытаюсь перезапустить Outlook.exe в Windows, используя C ++.

И этот код я использовал для перезапуска Outlook.

#include <TlHelp32.h>
void RestartOutlook() {
    PROCESSENTRY32 Pc = { sizeof(PROCESSENTRY32) };
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);

    MODULEENTRY32 Mo = {sizeof (MODULEENTRY32) };

    if(Process32First(hSnapshot, &Pc)){
        do{
            if(!_stricmp(Pc.szExeFile, "outlook.exe")) {
                DWORD pid = Pc.th32ProcessID;

                HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);

                //kill outlook
                HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
                DWORD fdwExit = 0;
                GetExitCodeProcess(process, &fdwExit);
                TerminateProcess(process, fdwExit);

                char * path;
                if (Module32First(hModuleSnapshot, &Mo)) {
                    path = Mo.szExePath;

                    STARTUPINFO si;
                    PROCESS_INFORMATION pi;
                    ZeroMemory(&si, sizeof(si));
                    si.cb = sizeof (si);
                    CreateProcess(path, NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS,
                        NULL, NULL, &si, &pi);
                }


            }
        }while(Process32Next(hSnapshot, &Pc));
    }
}

Самое смешное, что этот кусок кода прекрасно работает в Windows 7. В Windows XP (SP3) у меня дублируется Outlook.GetLastError дает мне 6: ERROR_INVALID_HANDLE.Я действительно невежествен после нескольких часов исследований.

Есть идеи?

В любом случае, C ++ - это не моя сфера деятельности.Я делаю паутину:)

А приведенный выше код представляет собой смесь следующих источников:

1: http://www.istorya.net/forums/programming/107435-how-can-i-kill-a-process-using-c.html

2: http://code.activestate.com/recipes/576362-list-system-process-and-process-information-on-win/

Среда: Windows 7, Windows XP, VS2010, Outlook 2003, Outlook 2007, Outlook 2010

Ответы [ 3 ]

4 голосов
/ 14 января 2011

Я нашел виновника.

Причина кроется в этой строке:

HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);

Согласно http://msdn.microsoft.com/en-us/library/ms684880(v=vs.85).aspx, PROCESS_ALL_ACCESS слишком велико для системы Windows XP / NTили более подробная информация:

Размер флага PROCESS_ALL_ACCESS увеличен в Windows Server 2008 и Windows Vista.Если приложение, скомпилированное для Windows Server 2008 и Windows Vista, выполняется в Windows Server 2003 или Windows XP / 2000, флаг PROCESS_ALL_ACCESS слишком велик, и функция, указывающая этот флаг, завершается ошибкой с ERROR_ACCESS_DENIED.Чтобы избежать этой проблемы, укажите минимальный набор прав доступа, требуемых для операции.

Определенно я компилирую эту программу на 7, а при запуске на XP определенно вызывает проблему.

Таким образом, решение состоит в том, чтобы изменить PROCESS_ALL_ACCESS на PROCESS_TERMINATE, что

HANDLE process = OpenProcess(PROCESS_TERMINATE, TRUE, pid);

Готово!

Спасибо @DReJ за быстрые ответы:)

2 голосов
/ 14 января 2011

Я понял, что вы хотите, чтобы Outlook перезагружался, но вызов TerminateProcess в Outlook кажется плохой идеей. Что, если он находится в процессе записи файла данных?

Лучшим способом было бы найти все окна верхнего уровня, относящиеся к Outlook, отправить им WM_CLOSE и затем дождаться завершения процесса. (Возможно, вам также придется справляться с тем, что у пользователя открыты черновики сообщений, что приводит к появлению подсказок «Вы уверены?», Хотя, если вы делаете это в первую очередь, то я предполагаю, что вы знаете, что пользователь не находится в центре внимания? )

Еще лучшим способом было бы использовать интерфейс автоматизации Outlook и явно отключить его.

1 голос
/ 14 января 2011

Возможно, ваша проблема связана с этим фрагментом кода

DWORD fdwExit = 0;
GetExitCodeProcess(process, &fdwExit);
TerminateProcess(process, fdwExit);

Сначала, с GetExitCodeProcess вы получаете статус STILL_ACTIVE, и после этого вы завершаете процесс с этим статусом, который, я думаю, является неправильным Удалите GetExitCodeProcess из вашего кода и попробуйте TerminateProcess(process, 0);.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...