自动关机,在delphi里面可以做出来么?

自动关机,在delphi里面可以做出来么?怎么做?能用代码写出来给小弟看么?
[38 byte] By [lwzl-冰室] at [2008-2-13]
# 1
可以用API实现,所以和开发工具无关!

function ShutDownSystem: Boolean;
var
VerInfo: TOSVersionInfo;
hToken: THANDLE;
tkp: TOKEN_PRIVILEGES;
Nothing: Cardinal;
begin
VerInfo.dwOSVersionInfoSize := SizeOf(VerInfo);
GetVersionEx(VerInfo);
if VerInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then begin
OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
hToken);
LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid);
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, tkp, 0, nil, Nothing);
end;
ExitWindowsEx(EWX_FORCE + EWX_SHUTDOWN + EWX_POWEROFF, 0);
Result:=True;
end;

98下
ExitWindowsEx(EWX_FORCE + EWX_SHUTDOWN + EWX_POWEROFF, 0);
就可以了,前面的代码用于在NT内核中获得足够权限!
ehom-?! at 2007-10-22 > top of Msdn China Tech,Delphi,VCL组件开发及应用...
# 2
function ShutDown(Action: integer): boolean;
//Designed by CK at xiamen, china;
const
ADJUST_PRIV = TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES;
SHTDWN_PRIV = 'SeShutdownPrivilege';
PRIV_SIZE = sizeOf(TTokenPrivileges);
var
uFlags: Cardinal;
Len: DWORD;
TokenPriv, Dummy: TTokenPrivileges;
Token: THandle;
Error: integer;
begin
error := 0;
if not OpenProcessToken(GetCurrentProcess(), ADJUST_PRIV, Token) then
Error := Error or 4;
if not LookupPrivilegeValue(nil, SHTDWN_PRIV, TokenPriv.Privileges[0].Luid) then
Error := Error or 8;
TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
TokenPriv.PrivilegeCount := 1; // One privilege to set
if not AdjustTokenPrivileges(Token, false, TokenPriv, PRIV_SIZE, Dummy, Len) then
Error := Error or 16;
case Action of
1: uFlags := EWX_POWEROFF + EWX_SHUTDOWN; //提示关机;
2: uFlags := EWX_POWEROFF + EWX_FORCE; //强制关机
3: uFlags := EWX_ReBoot; //提示重启系统
4: uFlags := EWX_ReBoot + EWX_FORCE; //强制重启系统
end;
ExitWindowsEx(uFlags, 0);
Result := (Error = 0);
end;
# 3
同意: ehom(?!)
# 4
控制WINDOWS的开关:如关闭WINDOWS,重新启动WINDOWS等, ExitWindowsEx(UINT uFlags,DWORD dwReserved);是实现这一功能的API函数
首先定义常数
const
EWX_FORCE=4; //关闭所有程序并以其他用户身份登录
EWX_LOGOFF=0; //重新启动计算机并切换到MS-DOS方式
EWX_REBOOT=2; //重新启动计算机
EWX_SHUTDOWN=1;//关闭计算机
运行时给How赋值,让他等于EWX_SHUTDOWN或其他,调用以下语句
ExitWindowsEx(How,0);

///////////////////////////////////////////
Function ShutDownWindows(Flags: Byte) : Boolean;
begin
Result := ExitWindowsEx(Flage, 0)
// 如果成功返回 True.
end;

Flags可用参数:

EWX_LOGOFF:
(=0)
安全地关闭所有进程,并关闭用户登录。

EWX_SHUTDOWN:
(=1)
关闭系统。所有缓冲区的内容都能被安全的存盘,所有进程都将被停止。
对于Windows NT: 必须有 SE_SHUTDOWN_NAME 的安全特权方可进行此项操作。
对于Windows 95: 不必有任何特权。

EWX_REBOOT:
(=2)
关闭并重新启动系统。
对于Windows NT: 必须有 SE_SHUTDOWN_NAME 的安全特权方可进行此项操作。
对于Windows 95: 不必有任何特权。

EWX_FORCE:
(=4)
强制切断连接,关闭所有应用程序。当使用这个参数时,Windows 将不向正在运行的应用程序发送 WM_QUERYENDSESSION 和 WM_ENDSESSION 消息,有可能造成数据丢失。所以推荐只在紧急时使用这个参数。

EWX_POWEROFF:
(=8)
关闭系统并切断电源,需要ATX电源支持。
/////////////////////////////////////
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);

private
{ Private declarations }
procedure AdjustToken;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.AdjustToken();
var
hdlProcessHandle : Cardinal;
hdlTokenHandle : Cardinal;
tmpLuid : Int64;
tkpPrivilegeCount : Int64;
tkp : TOKEN_PRIVILEGES;
tkpNewButIgnored : TOKEN_PRIVILEGES;
lBufferNeeded : Cardinal;
Privilege : array[0..0] of _LUID_AND_ATTRIBUTES;
begin
hdlProcessHandle := GetCurrentProcess;
OpenProcessToken(hdlProcessHandle,
(TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY),
hdlTokenHandle);

// Get the LUID for shutdown privilege.
LookupPrivilegeValue('', 'SeShutdownPrivilege', tmpLuid);
Privilege[0].Luid := tmpLuid;
Privilege[0].Attributes := SE_PRIVILEGE_ENABLED;
tkp.PrivilegeCount := 1; // One privilege to set
tkp.Privileges[0] := Privilege[0];
// Enable the shutdown privilege in the access token of this
// process.
AdjustTokenPrivileges(hdlTokenHandle,
False,
tkp,
Sizeof(tkpNewButIgnored),
tkpNewButIgnored,
lBufferNeeded);

end;
procedure TForm1.Button1Click(Sender: TObject);
begin
AdjustToken;
ExitWindowsEx((EWX_SHUTDOWN Or EWX_FORCE Or EWX_REBOOT), $FFFF);
end;

end.
# 5
当然可以了:

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

如何注销当前用户


# 6
可以使用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函数。