明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

關(guān)閉計算機就這幾招

[摘要]注:完全翻譯整理自MSDN。非常簡單. .“系統(tǒng)ShutDown”屬于Windows系統(tǒng)的一種基本服務(wù)。功能上有“關(guān)閉系統(tǒng)”,“注銷用戶”,“鎖定工作站”3中操作。SDK中提供了幾個函數(shù),來對此服務(wù)進行調(diào)用。“關(guān)閉系統(tǒng)”功能使計算機可以被安全的關(guān)閉。所有在文件系統(tǒng)里緩沖的內(nèi)容都被強制寫入磁盤。然后...
 
注:完全翻譯整理自MSDN。非常簡單. .

“系統(tǒng)ShutDown”屬于Windows系統(tǒng)的一種基本服務(wù)。功能上有“關(guān)閉系統(tǒng)”,“注銷用戶”,“鎖定工作站”3中操作。SDK中提供了幾個函數(shù),來對此服務(wù)進行調(diào)用。

“關(guān)閉系統(tǒng)”功能使計算機可以被安全的關(guān)閉。所有在文件系統(tǒng)里緩沖的內(nèi)容都被強制寫入磁盤。然后,顯示相應(yīng)的對話框,提示用戶計算機將被關(guān)閉或者已經(jīng)準備好被關(guān)閉?蛇x的情況一般是計算機在關(guān)閉后重起,而不是直接切斷電源。

如果一個進程調(diào)用“注銷”功能函數(shù),則該進程所在的安全環(huán)境范圍內(nèi)的所有進程都被終止,使當前的用戶退出系統(tǒng)。一個登陸對話框被顯示,期待新用戶的登陸。

“鎖定工作站”功能使你可以在離開計算機的時候,保護計算機屏幕不被未授權(quán)的用戶看到。要解除鎖定,必須用管理員或著授權(quán)用戶的帳號和密碼重新登陸。

如何關(guān)閉系統(tǒng):

程序可以用兩種方式關(guān)閉本地或遠程計算機
直接關(guān)閉系統(tǒng)
關(guān)閉系統(tǒng)并重啟
Windows NT/2000 及后續(xù)版本: 程序必須擁有SE_SHUTDOWN_NAME權(quán)限才能成功調(diào)用關(guān)閉函數(shù)。


ExitWindowsEx函數(shù)可以用來關(guān)閉系統(tǒng)。如函數(shù)成功調(diào)用,系統(tǒng)對每個窗口發(fā)送WM_QUERYENDSESSION 消息,詢問窗口所屬的程序是否可以被終止。收到此消息的程序應(yīng)該進行響應(yīng),清除環(huán)境釋放資源,然后返回TRUE表示自己可以被終止。然而調(diào)用ExitWindowEx的時候如果指定了EXW_FORCE,則系統(tǒng)強行終止相關(guān)的進程并關(guān)閉,這樣可能導(dǎo)致數(shù)據(jù)的丟失。

這是一段在NT/2000中調(diào)用ExitWindowEx關(guān)閉系統(tǒng)的程序(強制關(guān)閉所有程序)。

在windows95/98/me中直接調(diào)用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以及后續(xù)版本:

InitiateSystemShutdown函數(shù)可以指定一段延時,在進行延時計數(shù)的時候,在將被關(guān)閉的目標計算機上顯示一個對話框,提示用戶盡快注銷。一旦計數(shù)結(jié)束,系統(tǒng)則立刻被關(guān)閉。在此之前,可以調(diào)用AbortSystemShutdown函數(shù)停止計數(shù),取消相應(yīng)的關(guān)閉操作。InitiateSystemShutdown也可以指定讓系統(tǒng)重啟。


InitiateSystemShutdown有一個參數(shù)LPTSTR lpMachineName,可以指定為網(wǎng)絡(luò)上的計算機名字,也就是說,可以關(guān)閉網(wǎng)絡(luò)上的他計算機(如果你的用戶在該計算機上有足夠的權(quán)限的話)。


以下這個例子調(diào)用InitiateSystemShutdown函數(shù)關(guān)閉用戶已經(jīng)登陸的本地計算機(要關(guān)閉遠程計算機將InitSystemShutdown第一個參數(shù)由NULL改為正確的計算機名字或)。同樣的,也需要先獲得SE_SHUTDOWN_NAME權(quán)限。


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

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操作的代碼如下(記住要在延時結(jié)束前執(zhí)行才能起作用


// 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;

關(guān)于用戶權(quán)限(Privileges)的詳細信息,可以參見MSDN

如何注銷當前用戶


可以使用ExitWindows或ExitWindowsEx函數(shù)注銷當前用戶。

在默認的情況下,當程序調(diào)用ExitWindows或ExitWindowsEx注銷的時候,WM_QUERYENDSESSION消息也被發(fā)送到系統(tǒng)內(nèi)的每個窗口。窗口所屬的程序響應(yīng)此消息并且返回TRUE表示可以被關(guān)閉,如果任意一個程序返回FALSE,注銷操作將被取消。

Windows NT/2000以及后續(xù)版本:

當一個程序響應(yīng)WM_QUERYENDSESSION并返回TRUE,那么它就會立刻接受到WM_ENDSESSION消息并馬上結(jié)束,而不管其他的程序是怎么樣回應(yīng)WM_QUERYENDSESSION消息的。

Windows 95/98/Me:只有當系統(tǒng)內(nèi)所有的程序都對WM_QUERYENDSESSION消息回應(yīng)TRUE之后,他們才會一起接受到WM_ENDSESSION 消息,然后結(jié)束。

如果要強制關(guān)閉所有的程序,使用ExitWindowsEx函數(shù),指定EXW_FORCE標志。如果這樣做,系統(tǒng)不發(fā)送WM_QUERYENDSESSION 消息,而直接終止正在運行的程序。

在注銷的時候,系統(tǒng)還向每一個進程發(fā)送CTRL_LOGOFF_EVENT 控制碼?刂婆_程序可以注冊一個HandlerRoutine例程來處理這個控制碼(使用SetConsoleCtrlHandler函數(shù))。(更多的關(guān)于控制臺的控制碼,參見MSDN里“HandlerRoutine”有關(guān)章節(jié))

綜上所述:只有所有的程序都允許退出,注銷操作才能成功。如果某一個程序響應(yīng)WM_QUERYENDSESSION并返回FALSE ,用戶則不能被注銷。這樣就可以寫出防止用戶注銷或關(guān)閉的程序(非強制情況)。

//這是注銷當前用戶的代碼

ExitWindows(0, 0);

//響應(yīng)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函數(shù)即可鎖定工作站。系統(tǒng)會顯示一個鎖定對話框,告訴用戶此工作站正在使用并且已經(jīng)被鎖定,可以被執(zhí)行鎖定的用戶或管理員解鎖,解鎖的方式是按下CTRL_ALT_DEL并用正確的帳號和密碼登陸。

LockWorkStation函數(shù)成功調(diào)用的條件是:

調(diào)用者必須是運行在系統(tǒng)交互桌面上的一般進程。

必須已經(jīng)有用戶登陸到系統(tǒng)

工作站未被鎖定。

擁有正常窗口和消息隊列的程序通過WM_QUERYENDSESSION或WM_ENDSESSION消息獲得關(guān)閉通知。

控制臺則是在其控制流程(Handle Routines)里接受關(guān)閉通知。要注冊一個控制臺控制流程,應(yīng)該使用SetConsoleCtrlHandler函數(shù)

服務(wù)程序在其控制流程里接受退出通知。要注冊一個服務(wù)控制流程,應(yīng)該使用RegisterServiceCtrlHandlerEx函數(shù)。

關(guān)閉系統(tǒng)函數(shù)列表

函數(shù)名                函數(shù)功能描述

AbortSystemShutdown          取消由InitSystemShutdown引起的系統(tǒng)關(guān)閉操作

ExitWindows              注銷當前用戶

ExitWindowsEx             注銷用戶,關(guān)閉計算機,關(guān)閉計算機并且重啟

InitiateSystemShutdown         發(fā)起關(guān)閉系統(tǒng)操作,可以選擇關(guān)閉后重啟

InitiateSystemShutdownEx        同InitiateSystemShutdown,擴展的功能是可以在系統(tǒng)
                    事件日志(事件號6006)中寫入一個用戶指定的雙字節(jié)碼

LockWorkStation            鎖定工作站


系統(tǒng)關(guān)閉消息

WM_ENDSESSION

wParam

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

lParam

表示用戶注銷還是系統(tǒng)被關(guān)閉。如果此參數(shù)包含ENDSESSION_LOGOFF(lParam在這里是按位取值的)位,則表示是用戶注銷

Windows 2000 以及后續(xù)版本:如果lParam ==0,則表示系統(tǒng)被關(guān)閉。

程序收到此消息,如果wParam為TRUE,在完成消息處理后,程序隨時都有可能被關(guān)閉。所以在此消息的處理過程里,應(yīng)該盡量完成程序銷毀前所需要進行的工作。

WM_QUERYENDSESSION

wParam

保留,未使用

lParam

同WM_ENDSESSION;

DefWindowProc默認返回:TRUE