如何在 VC++ 2005 中使用 OpenProcessToken、AdjustTokenPrivileges 和 GetExitCodeProcess

Posted

技术标签:

【中文标题】如何在 VC++ 2005 中使用 OpenProcessToken、AdjustTokenPrivileges 和 GetExitCodeProcess【英文标题】:How to use OpenProcessToken, AdjustTokenPrivileges, and GetExitCodeProcess in VC++ 2005 【发布时间】:2012-01-17 16:26:08 【问题描述】:

我阅读了几篇关于如何检查一个进程是否已从另一个进程退出的帖子(我意识到有些人在这里迷上了语义,但只是幽默一下),我尝试实现它,但遇到了错误代码 5 ("ERROR_ACCESS_DENIED") 到处都是。

这就是我的工作。

1) 进程 1 (P1) 启动进程 2 并将其自己的 PID 写入共享内存位置。

2)进程2(P2)从共享内存中读取PID

3) P2 使用 P1 的 PID 调用 OpenProcess(...) 以保存它可以稍后检查的句柄。

4) P2 使用 P1 的 PID 反复调用 GetExitCodeProcess(...) 并检查 STILL_ACTIVE 代码。

在上述方法中,我在 GetExitCodeProcess 上不断收到 ACCESS_DENIED 错误。我尝试使用 MSDN 文档中的以下代码修改 P2 的权限:

HANDLE proc_h = OpenProcess(SYNCHRONIZE, FALSE, GetCurrentProcessId());
HANDLE hToken;
OpenProcessToken(proc_h, TOKEN_ADJUST_PRIVILEGES, &hToken);

LookupPrivilegeValue(NULL, lpszPrivilege, &luid );

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Enable the privilege
AdjustTokenPrivileges(hToken, 
                      FALSE, 
                      &tp, 
                      sizeof(TOKEN_PRIVILEGES), 
                      (PTOKEN_PRIVILEGES) NULL, 
                      (PDWORD) NULL);

但我在调用 OpenProcessToken(...) 方法时不断收到 ACCESS_DENIED 错误。那么这是否表明某种系统级别的障碍?我在我的机器上拥有管理员权限,并且我正在运行 XP。

提前感谢您的帮助。

【问题讨论】:

你能发布你的代码,在 P2 中打开 P1 的进程句柄吗?您是否在 OpenPROcess 的 desisredAccess 参数中指定 PROCESS_QUERY_INFORMATION 标志? @Bukes,hmjd 猜到了问题所在。我使用的是 SYNCHRONIZE 权限,而不是 PROCESS_QUERY_INFORMATION。 【参考方案1】:

传递给GetExitCodeProcess 的句柄需要PROCESS_QUERY_INFORMATION 访问权限。 以下工作正常:

int main(int a_argc, char** a_argv)

    int pid = atoi(*(a_argv + 1));

    HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);

    if (NULL != h)
    
        Sleep(2000);
        DWORD exit_code;
        if (FALSE == GetExitCodeProcess(h, &exit_code))
        
            std::cerr << "GetExitCodeProcess() failure: " <<
                GetLastError() << "\n";
        
        else if (STILL_ACTIVE == exit_code)
        
            std::cout << "Still running\n";
        
        else
        
            std::cout << "exit code=" << exit_code << "\n";
        
    
    else
    
        std::cerr << "OpenProcess() failure: " << GetLastError() << "\n";
    

    return 0;

不要轮询GetExitCodeProcess,而是用SYNCHRONIZE打开句柄并等待它退出:

int main(int a_argc, char** a_argv)

    int pid = atoi(*(a_argv + 1));

    HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid);

    if (NULL != h)
    
        WaitForSingleObject(h, 5000); // Change to 'INFINITE' wait if req'd
        DWORD exit_code;
        if (FALSE == GetExitCodeProcess(h, &exit_code))
        
            std::cerr << "GetExitCodeProcess() failure: " <<
                GetLastError() << "\n";
        
        else if (STILL_ACTIVE == exit_code)
        
            std::cout << "Still running\n";
        
        else
        
            std::cout << "exit code=" << exit_code << "\n";
        
    
    else
    
        std::cerr << "OpenProcess() failure: " << GetLastError() << "\n";
    

    return 0;

【讨论】:

【参考方案2】:

OpenProcesstoken 需要 PROCESS_QUERY_INFORMATION 您正在打开只有 SYNCHRONIZE 访问权限的进程。看看你加| PROCESS_QUERY_INFORMATION是否有效。

【讨论】:

【参考方案3】:

如果您只是希望 P2 在 P1 退出时做某事,还有另一种可能更简单的方法:让 P1 创建一个管道并让 P2 继承该管道的句柄。在 P2 中,从管道执行读取。当 P2 对 ReadFile 的调用返回错误 ERROR_BROKEN_PIPE 时,P1 已退出。

【讨论】:

以上是关于如何在 VC++ 2005 中使用 OpenProcessToken、AdjustTokenPrivileges 和 GetExitCodeProcess的主要内容,如果未能解决你的问题,请参考以下文章

visual stdio2005 如何像vc++6.0一样编译和调试啊

VC6.0和VS2005:C++和C#编写调用COM组件

vc++2005到2015都安装了,为啥还提示确实运行库

真的值得从 VC6 -> vc2005,2008 移植吗?

vc2005 webbrowser 怎么添加啊

导入 VC++2005 时 CString 出错?