如何通过Windows API关闭电脑?

3

我从未编写过winapi,所以在这里遇到了一些小问题。

我需要从我的应用程序中关闭计算机。

我找到了这个例子链接文本,然后我找到了这个例子,如何更改权限链接文本

但我有一个问题,如何获取该参数HANDLE hToken //访问令牌句柄

我认为我需要按照以下顺序进行操作以获取该参数 OpenProcessToken LookupPrivilegeValue AdjustTokenPrivileges 但是有很多参数我不知道该怎么处理。

也许你有一些示例可以告诉我如何获取该HANDLE hToken参数以使其工作。

顺便说一下,我已经看到了以下帖子链接文本

非常感谢大家。

6个回答

8
// ==========================================================================
// system shutdown
// nSDType: 0 - Shutdown the system
//          1 - Shutdown the system and turn off the power (if supported)
//          2 - Shutdown the system and then restart the system
void SystemShutdown(UINT nSDType)
{
    HANDLE           hToken;
    TOKEN_PRIVILEGES tkp   ;

    ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken);
    ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);

    tkp.PrivilegeCount          = 1                   ; // set 1 privilege
    tkp.Privileges[0].Attributes= SE_PRIVILEGE_ENABLED;

    // get the shutdown privilege for this process
    ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);

    switch (nSDType)
    {
        case 0: ::ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE, 0); break;
        case 1: ::ExitWindowsEx(EWX_POWEROFF|EWX_FORCE, 0); break;
        case 2: ::ExitWindowsEx(EWX_REBOOT  |EWX_FORCE, 0); break;
    }
}

5

4

你告诉我了我上面写的内容。然后我遇到了一个错误0x522——客户端没有所需的特权。这正是我一开始遇到的问题,也是我关于该参数的问题。感谢您的帮助。 - Night Walker
1
我喜欢这个答案,但根据文档,您不应该使用0作为第二个参数。除了其他问题之外,在重新启动时,它可能会将关闭报告为“非计划性的”,从而减慢事情的进展。可能值的列表可在http://msdn.microsoft.com/en-us/library/aa376885(VS.85).aspx上找到。我建议使用SHTDN_REASON_MAJOR_APPLICATION。 - T.E.D.

4

这段内容有点长,不太适合在丹尼尔的回答中进行讨论,所以我把它放在这里。

目前看来,你主要的问题是你的进程没有运行所需的权限来执行系统关闭操作。

ExitWindowsEx 的文档包含了以下内容:

为了关闭或重启系统, 调用进程必须使用 AdjustTokenPrivileges 函数来 启用 SE_SHUTDOWN_NAME 权限。 更多信息请参考 使用特殊权限运行

他们还提供了一些示例代码。如果需要,你可以直接复制这些代码。


我喜欢你的示例代码,甚至在gcc下使其工作。你知道这段代码和Jacob在页面下推荐的解决方案有什么区别吗?谢谢。 - Night Walker
嘿,谢谢,但是记录上应该是微软的代码,不是我的。 - T.E.D.
除非没有其他好的方法,否则我不会使用Jacob的方法。它可能也能工作,但它会创建一个完全独立的进程,然后将命令解释器加载到其中,然后进行目录搜索以查找shutdown.exe可执行文件,最后启动第三个进程来加载和运行它。当你无论如何都要关闭计算机时,这些额外的工作可能并不明显,但原则问题在于... - T.E.D.

0
#include<iostream>
using namespace std;
int main(){
system("shutdown -s -f -t 0");
}

0

关于 InitiateSystemShutdownEx 的一些工作代码:

// Get the process token
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
    &hToken);

// Build a token privilege request object for shutdown
TOKEN_PRIVILEGES tk;
tk.PrivilegeCount = 1;
tk.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(NULL, TEXT("SeShutdownPrivilege"), &tk.Privileges[0].Luid);

// Adjust privileges
AdjustTokenPrivileges(hToken, FALSE, &tk, 0, NULL, 0);

// Go ahead and shut down
InitiateSystemShutdownEx(NULL, NULL, 0, FALSE, FALSE, 0);

据我所知,与使用ExitWindowsEx解决方案相比,这种方法的优点在于调用进程不需要属于活动用户。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接