程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 實現系統注銷,重啟,關機的方法

C++ 實現系統注銷,重啟,關機的方法

編輯:C++入門知識

實現這一功能很簡單,主要需要調用一個系統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);//關機大家測試的時候一定要在虛擬機上測試,不然一運行系統熄火了豈不是很郁悶!

 

 

 

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved