【问题标题】:ERROR_INVALID_HANDLE on TerminateProcess (VS C++)TerminateProcess 上的 ERROR_INVALID_HANDLE (VS C++)
【发布时间】:2011-01-14 11:19:25
【问题描述】:

免责声明:这是该程序要求的一部分,因此它并不意味着任何不好的事情。如果您发现任何误用,请随时指出。我是 C++ 的初学者。

基本上,我正在尝试使用 C++ 在 Windows 上重新启动 Outlook.exe

这是我用来重启 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

【问题讨论】:

  • 我知道这可能会带来一些问题,为什么我应该重新启动 Outlook。这是因为我需要在一些修改后强制 Outlook 使用新的注册表值。当然,在执行此方法之前会要求多次确认。或者有其他选择吗?

标签: c++ windows winapi process outlook


【解决方案1】:

我找到了罪魁祸首。

原因在于这一行:

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

根据http://msdn.microsoft.com/en-us/library/ms684880(v=vs.85).aspxPROCESS_ALL_ACCESS对于Windows XP/NT系统来说太大了,或者更多细节:

在 Windows Server 2008 和 Windows Vista 上增加了 PROCESS_ALL_ACCESS 标志的大小。如果为 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】:

    我知道您希望 Outlook 重新启动,但首先在 Outlook 上调用 TerminateProcess 似乎是个坏主意。如果是在写数据文件呢?

    更好的方法是找到属于 Outlook 的所有顶级窗口,向它们发送 WM_CLOSE,然后等待进程退出。 (您可能还必须处理打开草稿消息的用户,这会导致“您确定”提示,尽管如果您首先这样做,那么我假设您知道用户不在某事中间? )

    更好的方法是使用 Outlook 的自动化界面并明确告诉它关闭。

    【讨论】:

    • 嗨,Leo,感谢您的提醒。但实际上这段代码属于我们项目的一部分,它是用 C++ 编写的,仅用于系统级修改。然后这个 exe 实际上是由我们在 Adob​​e Air 中的主应用程序调用的。所以实际上我们只会在用户确认后启动这个动作
    • 哦,感谢WM_CLOSE 的提醒。这是否类似于用户退出记事本但如果有未保存的作品,用户会收到警报?是的,我会调查这个谢谢!
    【解决方案3】:

    您的问题可能与这段代码有关

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

    首先,使用GetExitCodeProcess,您将获得STILL_ACTIVE 状态,然后您以这种状态终止进程,我认为这是不正确的。从您的代码中删除 GetExitCodeProcess,然后尝试使用 TerminateProcess(process, 0);

    【讨论】:

    • 不,我试过了,不能。我只是做TerminateProcess(process, 0);,但在 Windows XP 上,它返回6。 Windows 7 很好。
    • 仅供参考,在 Windows 7 上,GetExitCodeProcess 给出 259,在 Windows XP 上,GetExitCodeProcess 返回 0
    • 所以问题出在OpenProcess甚至早期
    • 是的,我刚刚发现。我的OpenProcess 返回NULL!任何的想法?为什么它只在 XP 上返回 NULL?
    • 您好,非常感谢您的患者。罪魁祸首找到了,我发布了解决方案。现在在 Windows XP 和 7 上运行良好。
    猜你喜欢
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 2015-11-12
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多