使用WinAPI实现关机重启Demo

发布于 2016-02-22  3453 次阅读


三种关机方式

  1. 物理断电
  2. shutdown -s -t (cmd命令)
  3. 使用Windows提供的API

关键API:ExitWindowsEX

MSDN有关ExitWindowsEx的介绍:https://msdn.microsoft.com/en-us/library/aa376868.aspx

百度百科有关ExitWindowsEx介绍:http://baike.baidu.com/link?url=B5BOS-LGyP3w6gOQObIkFIi9s5RQ4wPR0rz9vP-ssgp3wHc-Q1i3OxY8ePoPp7ViLTJyVT_Xmi0gCNikMG-MV_

demo

关键的实现代码

//提权函数(为ExiWtWindowEx函数提升权限)
bool EnableShutDownPriv()
{
	HANDLE hToken = nullptr;
	TOKEN_PRIVILEGES tkp = {0};
	bool bRet = false;
	do
	{
		// Get the token for this progress. 打开某一进程的访问令牌
		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
			break;

		//Get the LUID for the shutdown privilege. 修改进程的权限
		//if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &Luid))
		if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
			break;
		
		tkp.PrivilegeCount = 1;
		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		
		//Get the shutdown privilege for this process 通知Windows NT修改本进程的权利
		if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
			break;

		if (GetLastError() != ERROR_SUCCESS)
			break;
		
		bRet = true;
	} while (false);
	if (false == bRet){
		SetLastError(GetLastError());  //把最后错误信息抛出去
	}
	if (hToken){
		CloseHandle(hToken);
	}
	
	return bRet;
}

bool ReSetWindows(DWORD dwFlags, bool bForce)
{
	bool bRet = false;
	//提权
	do{
		if (EnableShutDownPriv()){
			if (!ExitWindowsEx(dwFlags, bForce)) // 第二个参数用来决定是否强制结束进程关机
				break;
		}
		bRet = true;
	} while (false);
	return bRet;
}

 

按钮事件

//关机按钮-事件处理函数
void CWinShutDownDlg::OnBnClickedOk()
{
	// TODO:  在此添加控件通知处理程序代码
	CDialogEx::OnOK();
	 
	ReSetWindows(EWX_SHUTDOWN, false);
}

风雨兼程路,雨雪初霁时