关于关机 ( 积分: 50 )

  • 主题发起人 主题发起人 zhoufujin
  • 开始时间 开始时间
Z

zhoufujin

Unregistered / Unconfirmed
GUEST, unregistred user!
下面代码为什么不能使win2k和winxp关机(win98可以)?
(关机进行到“您可以安全地关机了”,就停止了)
大家帮忙。
procedure Tform1.DoShutdown;
var
flgs: Cardinal;
tkp: _TOKEN_PRIVILEGES;
hdlTokenHandle: Cardinal;
tkpNewButIgnored: _TOKEN_PRIVILEGES;
lBufferNeeded: Cardinal;
timeDelay: Cardinal;
begin
flgs := 0;
flgs := flgs or EWX_FORCE or EWX_SHUTDOWN or EWX_PowerOff;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
FillChar(tkp, sizeof(tkp), 0);
OpenProcessToken(GetCurrentProcess, (TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY), hdlTokenHandle);
LookupPrivilegeValue('', 'SeShutdownPrivilege', tkp.Privileges[0].Luid);
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
tkp.PrivilegeCount := 1;
AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Sizeof(TOKEN_PRIVILEGES), tkpNewButIgnored, lBufferNeeded);
Caption := 'SHUTDOWN';
timeDelay := 0;
if not InitiateSystemShutdown(nil, nil, timeDelay, LongBool(True), LongBool(False)) then AbortSystemShutdown(nil);
end else
begin
ExitWindowsEx(flgs, 0);
end;
end;
 
下面代码为什么不能使win2k和winxp关机(win98可以)?
(关机进行到“您可以安全地关机了”,就停止了)
大家帮忙。
procedure Tform1.DoShutdown;
var
flgs: Cardinal;
tkp: _TOKEN_PRIVILEGES;
hdlTokenHandle: Cardinal;
tkpNewButIgnored: _TOKEN_PRIVILEGES;
lBufferNeeded: Cardinal;
timeDelay: Cardinal;
begin
flgs := 0;
flgs := flgs or EWX_FORCE or EWX_SHUTDOWN or EWX_PowerOff;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
FillChar(tkp, sizeof(tkp), 0);
OpenProcessToken(GetCurrentProcess, (TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY), hdlTokenHandle);
LookupPrivilegeValue('', 'SeShutdownPrivilege', tkp.Privileges[0].Luid);
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
tkp.PrivilegeCount := 1;
AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Sizeof(TOKEN_PRIVILEGES), tkpNewButIgnored, lBufferNeeded);
Caption := 'SHUTDOWN';
timeDelay := 0;
if not InitiateSystemShutdown(nil, nil, timeDelay, LongBool(True), LongBool(False)) then AbortSystemShutdown(nil);
end else
begin
ExitWindowsEx(flgs, 0);
end;
end;
 
换成我写的例程测试测试:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2675352
 
我在DFW上找到很多代码,其中包括您提供的,我都测试了,都是到
“您可以安全地关机了”为止,
不知道问题出在那了!
帮忙啊。
 
那就是你的硬件未支持电源管理。请先安装或在BIOS中设置好电源管理。

重要的:改变电源管理模式,可能导致无法进入系统!!!有可能需要重装系统。
 
"那就是你的硬件未支持电源管理。请先安装或在BIOS中设置好电源管理。"??
我的机器在使用win98时候用上述代码关机没问题,怎么能说“硬件未支持电源管理。请先安装或在BIOS中设置好电源管理”?
 
电源管理规范一直在发展,Windows2000刚出来的时候,有很多机器都碰到过无法自动
关机的问题,因Windows2000使用的规范不同,以前在98下可以正常关机的,在 2K 下
就不一定可以。您可以直接通过Windows2K或XP的开始菜单-->关机,选择关闭计算机,
看看操作系统是否可以把您的机器关至黑屏,如果操作系统也只是关到“您可以安全
地关机了”后就不动了,就是电源管理未打开或不支持。
 
您好:
多谢您的帮忙,您说的“您可以直接通过Windows2K或XP的开始菜单-->关机,选择关闭计算机,看看操作系统是否可以把您的机器关至黑屏”,其实不用测试,硬件和bios都支持,应为一个软件可以做到,其实不在于硬件和bios、以及电源管理,问题在于我们的程序,肯定在什么地方有问题。
您用我上面的代码测试一下,看看结果?
 
MSDN 的代碼如下, 但是我跟你的情況一樣, 都只係去到可以安全關閉系統那裡.

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");
 
继续帮忙啊,我非常需要这个功能
 
请问在delphi怎么样实现计算机重启,和关机(在win2000) (50分)
分类:数据库-C/S型 wangwsu (2003-01-16 21:56:00)
请问在delphi怎么样实现计算机重启,和关机(在win2000)

来如风 (2003-01-16 22:01:00)
Exitwindows(EWX_REBOOT,1)
重启,可以的啊

来如风 (2003-01-16 22:04:00)
Exitwindows(EWX_PowerOFF,1);//关闭计算机
如果关不了的话可能是有的进程没有结束掉吧,我有的时候可以关,有的时候不行

zw84611 (2003-01-16 22:08:00)
http://www.delphibbs.com/delphibbs/dispq.asp?lid=818372

lukecjh (2003-01-16 22:08:00)
我刚好写了一个,如下:
function TTimeForm.WinExitInNT(iFlags: Integer ): Boolean;
begin
Result := True;
if (SetPrivilege('SeShutdownPrivilege',True)) then
begin
if(not ExitWindowsEx(iFlags,0))then
begin
Result := False;
end;
SetPrivilege('SeShutdownPrivilege',False)
end else begin
Result := False;
end;
end;

function TTimeForm.SetPrivilege(sPrivilegeName: string; bEnabled: Boolean): Boolean;
var
TPPrev,TP: TTokenPrivileges;
Token: THandle;
dwRetLen: DWord;
begin
Result := False;
OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,Token);
TP.PrivilegeCount := 1;
if( LookupPrivilegeValue(Nil,PChar(sPrivilegeName),TP.Privileges[ 0 ].LUID )) then
begin
if(bEnabled) then
begin
TP.Privileges[ 0 ].Attributes := SE_PRIVILEGE_ENABLED;
end else begin
TP.Privileges[ 0 ].Attributes := 0;
end;
dwRetLen := 0;
Result := AdjustTokenPrivileges(Token,False,TP,SizeOf( TPPrev ),TPPrev,dwRetLen);
end;
CloseHandle(Token );
end;
if TeThemeRadioButton1.Checked then
WinExitInNT(EWX_SHUTDOWN);
if TeThemeRadioButton2.Checked then
WinExitInNT(EWX_REBOOT);


人在昆明 (2003-01-16 22:16:00)
看看这个未公开的 api
{
1、
BOOL InitiateSystemShutdownEx(
LPTSTR lpMachineName, // computer name
LPTSTR lpMessage, // message to display
DWORD dwTimeout, // length of time to display
BOOL bForceAppsClosed, // force closed option
BOOL bRebootAfterShutdown, // reboot option
DWORD dwReason // shutdown reason
);
2、
BOOL AbortSystemShutdown(
LPTSTR lpMachineName // computer name
);
}
function TForm1.ControlWin2K: Boolean;
var
GetDll: HWND;
InitiateSystemShutdownExA: function(
lpMachineName, lpMessage: string;
dwTimeout: DWord;
bForceAppsClosed, bRebootAfterShutdown: Boolean;
dwReason: DWord
): Integer; stdcall;
begin
GetDll := LoadLibrary(DllName);
try
if GetDll = 0 then
raise Exception.Create('加载Advapi32.dll出错,程序异常终止!');
@InitiateSystemShutdownExA := GetProcAddress(GetDll,
'InitiateSystemShutdownExA');
if @InitiateSystemShutdownExA <> nil then
begin
InitiateSystemShutdownExA('10.97.0.138', 'hi', 3000,
True, True, 0);
end;
end;
finally
freelibrary(GetDll);
end;


wangwsu (2003-01-16 22:24:00)
有没有重启方面的

人在昆明 (2003-01-16 22:26:00)
你查一下msdn 的帮助拉,好像 也是这个函数,只是参数不同,忘记拉
很久以前写的。
还有一个abort 什么的。

wangwsu (2003-09-11 12:22:00)
接受答案了.


lukecjh的回答最终被接受。
 
to zhoufujin: 把你的代碼修改一下就可以了~~
procedure Tform1.DoShutdown;
var
flgs: Cardinal;
tkp: _TOKEN_PRIVILEGES;
hdlTokenHandle: Cardinal;
tkpNewButIgnored: _TOKEN_PRIVILEGES;
lBufferNeeded: Cardinal;
timeDelay: Cardinal;
begin
flgs := EWX_POWEROFF;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
FillChar(tkp, sizeof(tkp), 0);
OpenProcessToken(GetCurrentProcess, (TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY), hdlTokenHandle);
LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid);
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
tkp.PrivilegeCount := 1;
AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Sizeof(TOKEN_PRIVILEGES), tkpNewButIgnored, lBufferNeeded);
Caption := 'SHUTDOWN';
timeDelay := 0;
ExitWindowsEx(EWX_POWEROFF, 0);
end;
end;
 
to zhoufujin: 把你的代碼修改一下就可以了~~
procedure Tform1.DoShutdown;
var
flgs: Cardinal;
tkp: _TOKEN_PRIVILEGES;
hdlTokenHandle: Cardinal;
tkpNewButIgnored: _TOKEN_PRIVILEGES;
lBufferNeeded: Cardinal;
timeDelay: Cardinal;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
FillChar(tkp, sizeof(tkp), 0);
OpenProcessToken(GetCurrentProcess, (TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY), hdlTokenHandle);
LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid);
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
tkp.PrivilegeCount := 1;
AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Sizeof(TOKEN_PRIVILEGES), tkpNewButIgnored, lBufferNeeded);
Caption := 'SHUTDOWN';
timeDelay := 0;
ExitWindowsEx(EWX_POWEROFF, 0);
end;
end;
 
在我的XP下可以/
 
不要写太复杂,用这个试试吧!
procedure TForm1.Button1Click(Sender: TObject);
var
lphandle:Thandle;
lpluid:int64;
privileges:TTokenPrivileges;
lpdword:Dword;
begin
openprocesstoken(getcurrentprocess(),Token_Adjust_Privileges or Token_Query,lphandle); //打开当前的进程进程标识
lookupprivilegevalue(nil,'seshutdownprivilege',lpluid); //得到特权属性
privileges.PrivilegeCount:=1; //得到特权类型
privileges.Privileges[0].Luid:=lpluid;
privileges.Privileges[0].Attributes:=SE_Privilege_Enabled; //将特权类型分配到进程标识
adjusttokenprivileges(lphandle,false,privileges,sizeof(privileges),privileges,lpdword);
exitwindowsex(EWX_Force or EWX_Poweroff,0);
end;
 
to zhoufujin: 問題應該解決了吧~~
 
下面代码经过测试可以作为万能关机。
谢谢诸位。
function TForm1.WinExitInNT(iFlags: Integer): Boolean;
begin
Result := True;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
if (SetPrivilege('SeShutdownPrivilege', True)) then
begin
if (not ExitWindowsEx(iFlags, 0)) then
begin
Result := False;
end;
SetPrivilege('SeShutdownPrivilege', False)
end else
begin
Result := False;
end;
end else
begin
Result := ExitWindowsEx(EWX_FORCE or EWX_SHUTDOWN or EWX_PowerOff, 0);
end;
end;

function TForm1.SetPrivilege(sPrivilegeName: string; bEnabled: Boolean): Boolean;
var
TPPrev, TP: TTokenPrivileges;
Token: THandle;
dwRetLen: DWord;
begin
Result := False;
OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token);
TP.PrivilegeCount := 1;
if (LookupPrivilegeValue(nil, PChar(sPrivilegeName), TP.Privileges[0].LUID)) then
begin
if (bEnabled) then
begin
TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
end else
begin
TP.Privileges[0].Attributes := 0;
end;
dwRetLen := 0;
Result := AdjustTokenPrivileges(Token, False, TP, SizeOf(TPPrev), TPPrev, dwRetLen);
end;
CloseHandle(Token);
end;
 
已经发分了,多谢。
 
這段寫得很好, 樓主是否忘記給分了, 提一下, 嘻
 
多人接受答案了。
 
后退
顶部