Delphi 5的问题,如题,此程序在Win98下运行成功: procedure TMainForm.btnExitClick(Sender: TObject);
begin
case rgExitOptions.ItemIndex of
Win32Check(ExitWindows(0, 0));
Win32Check(ExitWindowsEx(EWX_REBOOT, 0));
Win32Check(ExitWindowsEx(EWX_SHUTDOWN, 0));
Win32Check(ExitWindowsEx(EWX_LOGOFF, 0));
end; 但在Windows 2000下不可以直接退出,书本上有绍介,在NT环境下使用ExitWindowsEx()必须使用Win32 API函数AdjustTokenPrivleges()授予SE_SHUTDOWN_NAME权限,但我对Win32 API了解不多,上面的程序需要做哪些修改才可以在Windows 2000上正常使用呢?希望高手指点一二。 顺便问一问谁知道哪里有汉化的的Delphi帮助下载?虽然现在不是看不明白,但本身的英文水平太烂了,我是初学者,对于很多专业性很强的词汇很难理解,费时费力,学起来很慢,买来的书本虽然有介绍,但毕竟不全面。还有,请问哪位高手知道有什么Win32 API的好书籍,我想买好久了,请问您有什么好介绍吗?再贵我也会买。 另外,这是我在这里的第一次发帖,操作上还有些不明白,如果在给予分数的时候有什么失误,请您在QQ上与我联系,我的QQ号码是:397970,直接在通过检证时说明。我在线等候,谢谢!所有分数会给第一个成功解答的朋友,谢谢!
begin
case rgExitOptions.ItemIndex of
Win32Check(ExitWindows(0, 0));
Win32Check(ExitWindowsEx(EWX_REBOOT, 0));
Win32Check(ExitWindowsEx(EWX_SHUTDOWN, 0));
Win32Check(ExitWindowsEx(EWX_LOGOFF, 0));
end; 但在Windows 2000下不可以直接退出,书本上有绍介,在NT环境下使用ExitWindowsEx()必须使用Win32 API函数AdjustTokenPrivleges()授予SE_SHUTDOWN_NAME权限,但我对Win32 API了解不多,上面的程序需要做哪些修改才可以在Windows 2000上正常使用呢?希望高手指点一二。 顺便问一问谁知道哪里有汉化的的Delphi帮助下载?虽然现在不是看不明白,但本身的英文水平太烂了,我是初学者,对于很多专业性很强的词汇很难理解,费时费力,学起来很慢,买来的书本虽然有介绍,但毕竟不全面。还有,请问哪位高手知道有什么Win32 API的好书籍,我想买好久了,请问您有什么好介绍吗?再贵我也会买。 另外,这是我在这里的第一次发帖,操作上还有些不明白,如果在给予分数的时候有什么失误,请您在QQ上与我联系,我的QQ号码是:397970,直接在通过检证时说明。我在线等候,谢谢!所有分数会给第一个成功解答的朋友,谢谢!
解决方案 »
- SkinAdapter怎么使用?hook在哪里?addcontrol?
- 调用Windows中的Cards.dll的函数cdtdraw画出来的扑克牌如何擦除掉啊?
- Web Service是WAD的,TADOConnection连接数据库问题
- ExpressQuantumTreeList 4安装好后,启动 delphi6或delphi7都提示什么包错,没法用,只好卸了,哪位能给我解决吗?3Q
- 请问:如何安装calcomp控件?
- 简单问题,高分相送
- dbchart中,默认Y轴总是从数据源中选出的最小值开始,如何设为从0开始?
- 什么错误呢?
- 急急急!有谁能提供实用的dbTreeView控件
- IdFTP.List方法在有的网格下可以用,有的网络下报错,是何原因?
- 为什么会出现 access violation错误 请指导 急!!!!!
- 有哪位大虾知道是否有fastreport for d7?
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;
Privil
ege[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;
================================================================
◆◆◆ CSDN查询助手,查询方便快捷◆◆◆ 下载地址:
http://CoolSlob.ifood1.com/Download/CSDNFinder.exe
http://CoolSlob.8u8.com/Download/Tools/CSDNFinder.Slob[更名为.exe即可]
如何关闭系统: 程序可以用两种方式关闭本地或远程计算机
直接关闭系统
关闭系统并重启
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_ENDSESSIONwParam 表示是否要终止程序。如果是TRUE,指令该程序终止,否则是FALSElParam 表示用户注销还是系统被关闭。如果此参数包含ENDSESSION_LOGOFF(lParam在这里是按位取值的)位,则表示是用户注销Windows 2000 以及后续版本:如果lParam ==0,则表示系统被关闭。程序收到此消息,如果wParam为TRUE,在完成消息处理后,程序随时都有可能被关闭。所以在此消息的处理过程里,应该尽量完成程序销毁前所需要进行的工作。WM_QUERYENDSESSION wParam 保留,未使用lParam 同WM_ENDSESSION;DefWindowProc默认返回:TRUE
function ShutDownSystem():BOOL;
var
hProcess,hAccessToken:THandle;
LUID_AND_ATTRIBUTES:TLUIDAndAttributes;
TOKEN_PRIVILEGES: TTokenPrivileges;
BufferIsNull:DWORD;
Const
SE_SHUTDOWN_NAME='SeShutdownPrivilege';
begin
hProcess:=GetCurrentProcess();OpenProcessToken(hprocess,TOKEN_ADJUST_PRIVILEGES+TOKEN_QUERY,hAccessToken);
LookupPrivilegeValue(Nil,SE_SHUTDOWN_NAME,LUID_AND_ATTRIBUTES.Luid);
LUID_AND_ATTRIBUTES.Attributes:=SE_PRIVILEGE_ENABLED;
TOKEN_PRIVILEGES.PrivilegeCount:=1;
TOKEN_PRIVILEGES.Privileges[0]:=LUID_AND_ATTRIBUTES;
BufferIsNull:=0;AdjustTokenPrivileges(hAccessToken,False,TOKEN_PRIVILEGES,sizeof(TOKEN_PRIVI
LEGES),Nil,BufferIsNull);
ExitWindowsEx(EWX_REBOOT, 0);
ShutDownSystem:=True;
end;关闭系统并切断电源,需要ATX电源支持。
/////////////////////////////////////
unit Unit1;interfaceuses
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.