我的应用程序使用Windows的未公开的函数SHChangeNotifyRegister及SHChangeNotifyDeRegister来监视WIndows文件操作,正常关闭程序,一切正常。
但如果不结束应用程序,Windows 9X/2000均无法关闭/注销计算机。
请高手指点:如何解决不结束应用程序而不影响Windows关闭.
但如果不结束应用程序,Windows 9X/2000均无法关闭/注销计算机。
请高手指点:如何解决不结束应用程序而不影响Windows关闭.
调试欢乐多
procedure ExitWindowsNT(uFlags : integer);
var
hToken : THANDLE;
tkp, tkDumb : TTokenPrivileges;
DumbInt : integer;
begin
FillChar(tkp, sizeof(tkp), 0);
// Get a token for this process
if not (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES
or TOKEN_QUERY, hToken)) then
raise Exception.create('OpenProcessToken failed with code '
+ inttostr(GetLastError)); // Get the LUID for the Shutdown privilege
LookupPrivilegeValue(nil, pchar('SeShutdownPrivilege'),
tkp.Privileges[0].Luid); tkp.PrivilegeCount := 1; // one privilege to set
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; // Get the shutdown provolege for this process
AdjustTokenPrivileges(hToken, false, tkp, sizeof(tkDumb), tkDumb, DumbInt); // Cannot test the return value of AdjustTokenPrivileges
if GetLastError <> ERROR_SUCCESS then
Raise Exception.create('AdjustTokenPrivileges failed with code '
+ inttostr(GetLastError)); // shut down the system and for all applications to close
if not ExitWindowsEx(uFlags, 0) then
Raise Exception.create('ExitWindowsEx failed with code '
+ inttostr(GetLastError));
end;
本函数详细的说明请查看有关文档,我以前做过类似的东西,测试成功,没有任何问题!
至于要实现的操作(如关机或重启),在于函数的返回值,可以自己定夺。
“关闭Windows(应该是关机)”,“使Windows重启”等功能,返回值布尔类型。 ExitWindowsEx(关闭类型参数,系统保留参数) 系统保留参数一般为0。 关闭类型参数: EWX_FORCE :强制关闭,不会发送任何消息给正在运行的程序,强行关闭Windows。 EWX_LOGOFF :注销当前用户,并重新登陆。 EWX_POWEROFF :关闭Windows,并关机(主板需支持软关机,就是电源管理啦) EWX_REBOOT :不用说了Reboot重启系统 EWX_SHUTDOWN :安全关闭Windows,书上说缓冲区内数据将被写入磁盘。 EWX_FORCEIFHUNG :在Windows2000以上版本中才有,用EWX_FORCE就很好。 example: ExitWindowsEx(ewx_logooff,0);//注销用户 ExitWindowsEx(ewx_reboot,0);//重启系统 ExitWindowsEx(ewx_shutdown,0);//安全关机(软关机) 另外在WindowsNT版本中(NT4,Win2000,WinXP)调用这些函数必须具有系统管理员身份 或使SE_SHUTDOWN_NAME特权有效才能关机。 另外ExitWindows()函数只能注销当前用户,调用为ExitWindows(0,0)返回值为布尔类 型。
if Win32Platform <> VER_PLATFORM_WIN32_NT then //不是NT
ExitWindowsEx(EWX_REBOOT, 0)
else
begin
SetPrivilege('SeShutdownPrivilege', True);
if not ExitWindowsEx(EWX_REBOOT + EWX_FORCE, 0) then
SetPrivilege('SeShutdownPrivilege', False);
end; //--关机
if Win32Platform <> VER_PLATFORM_WIN32_NT then //不是NT
ShellExecute(handle, 'open', 'RUNDLL32.EXE', 'user.exe,ExitWindows', nil, SW_ShowNormal)
else
begin
SetPrivilege('SeShutdownPrivilege', True);
if not ExitWindowsEx(EWX_SHUTDOWN + EWX_FORCE+EWX_POWEROFF, 0) then
SetPrivilege('SeShutdownPrivilege', False);
end;
Form1: TForm1;implementation{$R *.dfm}procedure AdjustToken();
var
hdlProcessHandle : Cardinal;
hdlTokenHandle : Cardinal;
tmpLuid : 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 ShutDown(uFlags: Cardinal);
begin
AdjustToken;
//ExitWindowsEx(EWX_LOGOFF , 0);
//ExitWindowsEx(EWX_SHUTDOWN, 0);
//ExitWindowsEx(EWX_REBOOT , 0);
//ExitWindowsEx(EWX_FORCE , 0);
ExitWindowsEx(uFlags, 0);
//ExitWindowsEx(EWX_FORCEIFHUNG , 0);
{EWX_FORCE or EWX_SHUTDOWN,0}
end;
procedure TForm1.BitBtn2Click(Sender: TObject);//注销
begin
ShutDown(EWX_FORCE or EWX_LOGOFF);
end;procedure TForm1.BitBtn3Click(Sender: TObject);//关机
begin
ShutDown(EWX_FORCE or EWX_POWEROFF);
end;procedure TForm1.BitBtn4Click(Sender: TObject);//重启
begin
ShutDown(EWX_FORCE or EWX_REBOOT);
end;