灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:3168回复:0

[C++技术]C++ 实现系统注销,重启,关机的方法

楼主#
更多 发布于:2013-05-21 10:35

实现这一功能很简单,主要需要调用一个系统API

ExitWindowsEx

功能就是,注销当前用户,关闭系统,或者重新启动系统。

它会发送一个WM_QUERYENDSESSION消息给所有的应用程序,让他们决定是不是可以被关闭。

函数原型

[cpp]  <SPAN style="FONT-SIZE: 18px">BOOL WINAPI ExitWindowsEx(

  __in  UINT uFlags,

  __in  DWORD dwReason

);

</SPAN>

BOOL WINAPI ExitWindowsEx(

  __in  UINT uFlags,

  __in  DWORD dwReason

);

第一个参数是关闭类型,第二个是关闭的原因

第一个参数可以是:

EWX_LOGOFF

0

EWX_POWEROFF

0x00000008

EWX_REBOOT

0x00000002

EWX_RESTARTAPPS

0x00000040

EWX_SHUTDOWN

0x00000001

这个参数还可以可选的包含下面两个值

EWX_FORCE

0x00000004       包含这个参数可以让系统强制关机,可能会让应用程序丢失数据

EWX_FORCEIFHUNG

0x00000010

如果在超时时间以后应用进程仍然没有响应WM_QUERYENDSESSION或WM_ENDSESSION消息,那么就强制关闭它们。

返回值:

成功的话返回非0值,失败返回0

可以通过GetLastError()获得更多错误信息。

除了了解这个函数以外,我们还应该清楚:

对于windows NT以上版本的操作系统,我们需要提升一个SE_SHUTDOWN权限,才能完成关机的操作。

NT一下的则不需要,例如95,98,ME

NT以上的系统包括:

Microsoft Windows 2000 (Windows NT 5.0) (1999) (2000-2010)

Microsoft Windows XP (Windows NT 5.1) (2001-2014)

Microsoft Windows Server 2003 (Windows NT 5.2) (2003-2015)

Microsoft Windows Server 2003 R2 (Windows NT 5.2) (2006-2015)

Microsoft Windows Vista (Windows NT 6.0) (2006-2017)

Microsoft Windows Server 2008 (Windows NT 6.0) (2008-2018)

Microsoft Windows 7 (Windows NT 6.1) (2009-2020)

下面我们开始具体实现:

关机功能实现

1.检查系统版本,看是不是NT以上,如果是则要提升权限

2.调用系统API,ExitWindowsEx。

[cpp]  #pragma region 功能实现  

BOOL ReSetWindows(DWORD dwFlags,BOOL bForce)

{

    //检查参数是否正确  

    if(dwFlags!=EWX_LOGOFF&&dwFlags!=EWX_REBOOT&&dwFlags!=EWX_SHUTDOWN)

        return FALSE;

    //获得系统的版本信息,让我们后面确定是否需要提升系统权限  

    OSVERSIONINFO osvi={0};

    //获得参数的大小,以提供给GetVersionEx来判断这是一个新版本的OSVERSIONINFO,还是旧版本的  

    //新版本是OSVERSIONINFOEX。扩充版本  

    osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);

    if(!GetVersionEx(&osvi))

    {

        return FALSE;

    }

    //检查操作系统的版本,如果是NT类型的系统,需要提升系统权限  

    if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)

    {

        //EnableShutDownPriv();  

    }

    //判断是否是强制关机,强制关闭系统进程。  

    dwFlags|=(bForce!=FALSE)?EWX_FORCE:EWX_FORCEIFHUNG;

    //调用API  

    return ExitWindowsEx(dwFlags,0);

}

#pragma region 功能实现

BOOL ReSetWindows(DWORD dwFlags,BOOL bForce)

{

 //检查参数是否正确

 if(dwFlags!=EWX_LOGOFF&&dwFlags!=EWX_REBOOT&&dwFlags!=EWX_SHUTDOWN)

  return FALSE;

 //获得系统的版本信息,让我们后面确定是否需要提升系统权限

 OSVERSIONINFO osvi={0};

 //获得参数的大小,以提供给GetVersionEx来判断这是一个新版本的OSVERSIONINFO,还是旧版本的

 //新版本是OSVERSIONINFOEX。扩充版本

 osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);

 if(!GetVersionEx(&osvi))

 {

  return FALSE;

 }

 //检查操作系统的版本,如果是NT类型的系统,需要提升系统权限

 if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)

 {

  //EnableShutDownPriv();

 }

 //判断是否是强制关机,强制关闭系统进程。

 dwFlags|=(bForce!=FALSE)?EWX_FORCE:EWX_FORCEIFHUNG;

 //调用API

 return ExitWindowsEx(dwFlags,0);

}提升权限的代码:

[cpp]  #pragma region 用来提升系统权限  

//这是一个通用的提升权限函数,如果需要提升其他权限  

//更改LookupPrivilegeValue的第二个参数SE_SHUTDOWN_NAME,即可  

BOOL EnableShutDownPriv()

{

    HANDLE hToken=NULL;

    TOKEN_PRIVILEGES tkp={0};

    //打开当前程序的权限令牌  

    if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))

    {

        return FALSE;

    }

    //获得某一特定权限的权限标识LUID,保存在tkp中  

    if (!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid))

    {

        CloseHandle(hToken);

        return FALSE;

    }

    tkp.PrivilegeCount=1;

    tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

    //调用AdjustTokenPrivileges来提升我们需要的系统权限  

    if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))

    {

        CloseHandle(hToken);

        return FALSE;

    }

    return TRUE;

}

#pragma region 用来提升系统权限

//这是一个通用的提升权限函数,如果需要提升其他权限

//更改LookupPrivilegeValue的第二个参数SE_SHUTDOWN_NAME,即可

BOOL EnableShutDownPriv()

{

 HANDLE hToken=NULL;

 TOKEN_PRIVILEGES tkp={0};

 //打开当前程序的权限令牌

 if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))

 {

  return FALSE;

 }

 //获得某一特定权限的权限标识LUID,保存在tkp中

 if (!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid))

 {

  CloseHandle(hToken);

  return FALSE;

 }

 tkp.PrivilegeCount=1;

 tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

 //调用AdjustTokenPrivileges来提升我们需要的系统权限

 if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))

 {

  CloseHandle(hToken);

  return FALSE;

 }

 return TRUE;

}调用方法:

[cpp]  ReSetWindows(EWX_LOGOFF,false);//注销

ReSetWindows(EWX_LOGOFF,false);//注销[cpp] view plaincopyprint?ReSetWindows(EWX_REBOOT,true);//重启

ReSetWindows(EWX_REBOOT,true);//重启[cpp] view plaincopyprint?ReSetWindows(EWX_SHUTDOWN,true);//关机

ReSetWindows(EWX_SHUTDOWN,true);//关机大家测试的时候一定要在虚拟机上测试,不然一运行系统熄火了岂不是很郁闷!


喜欢0 评分0
游客

返回顶部