關閉電腦就這幾招

來源:互聯網
上載者:User
註:完全翻譯整理自MSDN。非常簡單. .

“系統ShutDown”屬於Windows系統的一種基本服務。功能上有“關閉系統”,“登出使用者”,“鎖定工作站”3中操作。SDK中提供了幾個函數,來對此服務進行調用。

“關閉系統”功能使電腦可以被安全的關閉。所有在檔案系統裡緩衝的內容都被強制寫入磁碟。然後,顯示相應的對話方塊,提示使用者電腦將被關閉或者已經準備好被關閉。可選的情況一般是電腦在關閉後重起,而不是直接切斷電源。

如果一個進程調用“登出”功能函數,則該進程所在的安全環境範圍內的所有進程都被終止,使當前的使用者退出系統。一個登陸對話方塊被顯示,期待新使用者的登陸。

“鎖定工作站”功能使你可以在離開電腦的時候,保護電腦螢幕不被未授權的使用者看到。要解除鎖定,必須用管理員或著授權使用者的帳號和密碼重新登陸。

如何關閉系統: 

程式可以用兩種方式關閉本地或遠端電腦

直接關閉系統

關閉系統並重啟

Windows NT/2000 及後續版本: 程式必須擁有SE_SHUTDOWN_NAME許可權才能成功調用關閉函數。 

ExitWindowsEx函數可以用來關閉系統。如函數成功調用,系統對每個視窗發送WM_QUERYENDSESSION 訊息,詢問視窗所屬的程式是否可以被終止。收到此訊息的程式應該進行響應,清除環境釋放資源,然後返回TRUE表示自己可以被終止。然而調用ExitWindowEx的時候如果指定了EXW_FORCE,則系統強行終止相關的進程並關閉,這樣可能導致資料的丟失。

這是一段在NT/2000中調用ExitWindowEx關閉系統的程式(強制關閉所有程式)。

在windows95/98/me中直接調用ExitWindowEx即可。

-----------------------------------------------------------------------------------------------------------

HANDLE hToken; 

TOKEN_PRIVILEGES tkp; 

// Get a token for this process. 

if (!OpenProcessToken(GetCurrentProcess(), 

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 

Error("OpenProcessToken"); 

// Get the LUID for the shutdown privilege. 

LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 

&tkp.Privileges[0].Luid); 

tkp.PrivilegeCount = 1; // one privilege to set 

tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

// Get the shutdown privilege for this process. 

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 

(PTOKEN_PRIVILEGES)NULL, 0); 

// Cannot test the return value of AdjustTokenPrivileges. 

if (GetLastError() != ERROR_SUCCESS) 

error("AdjustTokenPrivileges"); 

// Shut down the system and force all applications to close. 

if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0)) 

error("ExitWindowsEx");

-----------------------------------------------------------------------------------------------------------

Windows NT/2000以及後續版本: 

InitiateSystemShutdown函數可以指定一段延時,在進行延時計數的時候,在將被關閉的目標電腦上顯示一個對話方塊,提示使用者儘快登出。一旦計數結束,系統則立刻被關閉。在此之前,可以調用AbortSystemShutdown函數停止計數,取消相應的關閉操作。InitiateSystemShutdown也可以指定讓系統重啟。

InitiateSystemShutdown有一個參數LPTSTR lpMachineName,可以指定為網路上的電腦名稱字,也就是說,可以關閉網路上的他電腦(如果你的使用者在該電腦上有足夠的許可權的話)。

以下這個例子調用InitiateSystemShutdown函數關閉使用者已經登陸的本機電腦(要關閉遠端電腦將InitSystemShutdown第一個參數由NULL改為正確的電腦名稱字或)。同樣的,也需要先獲得SE_SHUTDOWN_NAME許可權。

---------------------------------------------------------------------------------------------------------

HANDLE hToken; // handle to process token 

TOKEN_PRIVILEGES tkp; // pointer to token structure 

BOOL fResult; // system shutdown flag 

// Get the current process token handle so we can get shutdown 

// privilege. 

if (!OpenProcessToken(GetCurrentProcess(), 

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 

ErrorHandler("OpenProcessToken failed."); 

// Get the LUID for shutdown privilege. 

LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 

&tkp.Privileges[0].Luid); 

tkp.PrivilegeCount = 1; // one privilege to set 

tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

// Get shutdown privilege for this process. 

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 

(PTOKEN_PRIVILEGES) NULL, 0); 

// Cannot test the return value of AdjustTokenPrivileges. 

if (GetLastError() != ERROR_SUCCESS) 

ErrorHandler("AdjustTokenPrivileges enable failed."); 

// Display the shutdown dialog box and start the time-out countdown. 

fResult = InitiateSystemShutdown( 

NULL, // shut down local computer 

"Click on the main window and press \

the Escape key to cancel shutdown.", // message to user 

20, // time-out period 

FALSE, // ask user to close apps 

TRUE); // reboot after shutdown 

if (!fResult) 

{

ErrorHandler("InitiateSystemShutdown failed."); 



// Disable shutdown privilege. 

tkp.Privileges[0].Attributes = 0; 

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 

(PTOKEN_PRIVILEGES) NULL, 0); 

if (GetLastError() != ERROR_SUCCESS) 

{

ErrorHandler("AdjustTokenPrivileges disable failed."); 

---------------------------------------------------------------------------------------------

而使用AbortSystemShutoown取消InitialSystemShutdown操作的代碼如下(記住要在延時結束前執行才能起作用

// Get the current process token handle so we can get shutdown 

// privilege. 

if (!OpenProcessToken(GetCurrentProcess(), 

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 

{

ErrorHandler("OpenProcessToken failed."); 

}

// Get the LUID for shutdown privilege. 

LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 

&tkp.Privileges[0].Luid); 

tkp.PrivilegeCount = 1; // one privilege to set 

tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

// Get shutdown privilege for this process. 

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 

(PTOKEN_PRIVILEGES)NULL, 0); 

// Cannot test the return value of AdjustTokenPrivileges. 

if (GetLastError() != ERROR_SUCCESS) 

{

ErrorHandler("AdjustTokenPrivileges enable failed."); 

}

// Prevent the system from shutting down. 

fResult = AbortSystemShutdown(NULL); 

if (!fResult) 



ErrorHandler("AbortSystemShutdown failed."); 

// Disable shutdown privilege. 

tkp.Privileges[0].Attributes = 0; 

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 

(PTOKEN_PRIVILEGES) NULL, 0); 

if (GetLastError() != ERROR_SUCCESS) 

{

ErrorHandler("AdjustTokenPrivileges disable failed."); 

}

break; 

關於使用者權限(Privileges)的詳細資料,可以參見MSDN

如何登出目前使用者 

可以使用ExitWindows或ExitWindowsEx函數登出目前使用者。

在預設的情況下,當程式調用ExitWindows或ExitWindowsEx登出的時候,WM_QUERYENDSESSION訊息也被發送到系統內的每個視窗。視窗所屬的程式響應此訊息並且返回TRUE表示可以被關閉,如果任意一個程式返回FALSE,登出操作將被取消。

Windows NT/2000以及後續版本: 

當一個程式響應WM_QUERYENDSESSION並返回TRUE,那麼它就會立刻接受到WM_ENDSESSION訊息並馬上結束,而不管其他的程式是怎麼樣回應WM_QUERYENDSESSION訊息的。

Windows 95/98/Me:只有當系統內所有的程式都對WM_QUERYENDSESSION訊息回應TRUE之後,他們才會一起接受到WM_ENDSESSION 訊息,然後結束。

如果要強制關閉所有的程式,使用ExitWindowsEx函數,指定EXW_FORCE標誌。如果這樣做,系統不發送WM_QUERYENDSESSION 訊息,而直接終止正在啟動並執行程式。

在登出的時候,系統還向每一個進程發送CTRL_LOGOFF_EVENT 控制碼。控制台程式可以註冊一個HandlerRoutine常式來處理這個控制碼(使用SetConsoleCtrlHandler函數)。(更多的關於控制台的控制碼,參見MSDN裡“HandlerRoutine”有關章節)

綜上所述:只有所有的程式都允許退出,登出操作才能成功。如果某一個程式響應WM_QUERYENDSESSION並返回FALSE ,使用者則不能被登出。這樣就可以寫出防止使用者登出或關閉的程式(非強制情況)。

//這是登出目前使用者的代碼

ExitWindows(0, 0); 

//響應WM_QUERYENDSESSION訊息,如果在彈出訊息框裡選擇NO,則取消登出。

case WM_QUERYENDSESSION: 



int r; 

r = MessageBox(NULL, "Shut down?","WM_QUERYENDSESSION", MB_YESNO); 

// Return TRUE to allow shutdown, FALSE to stop. 

return r == IDYES; 

break; 



如何鎖定工作站 

使用LockWorkStation函數即可鎖定工作站。系統會顯示一個鎖定對話方塊,告訴使用者此工作站正在使用並且已經被鎖定,可以被執行鎖定的使用者或管理員解鎖,解鎖的方式是按下CTRL_ALT_DEL並用正確的帳號和密碼登陸。

LockWorkStation函數成功調用的條件是:

調用者必須是運行在系統互動式桌面上的一般進程。 

必須已經有使用者登陸到系統 

工作站未被鎖定。 

接受關閉通知 

擁有正常視窗和訊息佇列的程式通過WM_QUERYENDSESSION或WM_ENDSESSION訊息獲得關閉通知。

控制台則是在其控制流程程(Handle Routines)裡接受關閉通知。要註冊一個控制台控制流程程,應該使用SetConsoleCtrlHandler函數

服務程式在其控制流程程裡接受退出通知。要註冊一個服務控制流程程,應該使用RegisterServiceCtrlHandlerEx函數。

關閉系統函數列表 

函數名                函數功能描述 

AbortSystemShutdown          取消由InitSystemShutdown引起的系統關閉操作

ExitWindows              登出目前使用者

ExitWindowsEx             登出使用者,關閉電腦,關閉電腦並且重啟

InitiateSystemShutdown         發起關閉系統操作,可以選擇關閉後重啟

InitiateSystemShutdownEx        同InitiateSystemShutdown,擴充的功能是可以在系統

                    事件記錄(事件號6006)中寫入一個使用者指定的雙位元組碼

LockWorkStation            鎖定工作站

系統關閉訊息 

WM_ENDSESSION

wParam 

表示是否要終止程式。如果是TRUE,指令該程式終止,否則是FALSE

lParam 

表示使用者登出還是系統被關閉。如果此參數包含ENDSESSION_LOGOFF(lParam在這裡是按位取值的)位,則表示是使用者登出

Windows 2000 以及後續版本:如果lParam ==0,則表示系統被關閉。

程式收到此訊息,如果wParam為TRUE,在完成訊息處理後,程式隨時都有可能被關閉。所以在此訊息的處理過程裡,應該盡量完成程式銷毀前所需要進行的工作。

WM_QUERYENDSESSION 

wParam 

保留,未使用

lParam 

同WM_ENDSESSION;

DefWindowProc預設返回:TRUE

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.