关于关机命令
请问以下关机命令在Win2000下好像不行耶。而且i = ExitWindowsEx(EWX_FORCE, 0)在Win98下也不行,但i = ExitWindowsEx(EWX_SHUTDOWN, 0)可以,请指点迷津。
call AdjustTokenPrivilegesForNT
i = ExitWindowsEx(EWX_SHUTDOWN, 0)
Public Function AdjustTokenPrivilegesForNT()
Dim hdlProcessHandle As Long
Dim hdlTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpNewButIgnored As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long
tmpLuid.highpart = 1
tmpLuid.lowpart = 1
hdlProcessHandle = GetCurrentProcess()
OpenProcessToken hdlProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or Token_query), hdlTokenHandle
LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
tkp.PrivilegeCount = 1
tkp.Privileges(0).pLuid = tmpLuid
tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded
End Function
问题点数:20、回复次数:12Top
1 楼Wesely(我就是我)回复于 2001-11-14 12:33:05 得分 0
EWX_FORCE只是一个选项,应该和EWX_SHUTDOWN一起用:
ExitWindowEX(EWX_SHUTDOWN or EWX_FORCE,0)
在Win2K里,我这台机子是可以关机,只是不会自动断电。也不知道是什么问题。Top
2 楼redbirdli(火鸟)回复于 2001-11-14 13:17:22 得分 10
由于NT/2k特有的安全机制与9x是不同的,以下代码才能重启或关闭,只ExitWindowEx 时只能注销而已
以下是个delphi的例子,vb也一样吗!
在2k中要想关机应该用 EWX_POWEROFF参数而不是EWX_SHUTDOWN
var stmp:string;
htmp,hToken:Thandle;
tkp:TOKEN_PRIVILEGES;
tkpOld:TOKEN_PRIVILEGES;
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, sizeof(tkpOld), tkpOld, htmp);
ExitwindowsEx(EWX_POWEROFF,0);
end;
delphi经典之作 http://rbsky.myetang.com/SuperEx.exe 已实现了2k下的重启及关机
火鸟天堂 http://rbsky.myetang.com
Top
3 楼NightBreak(菜鸟2004)回复于 2001-11-14 13:24:37 得分 0
我好像总用这个,简单多了 :)
shell "Rundll32 user32.dll,EXITWINDOWS"
Top
4 楼basey(千错万错都是我的错)回复于 2001-11-14 14:18:19 得分 0
EWX_POWEROFF值是多少啊?我在API Text Viewer里只能看到EWX_FORCE,EWX_LOGOFF,EWX_REBOOT,EWX_SHUTDOWN,是不是我的WIN32API.txt不够新啊?Top
5 楼uguess(天地间,有我在行走!)回复于 2001-11-14 14:40:27 得分 0
Public Const EWX_POWEROFF = &H00000008
Top
6 楼crank_crank(crank)回复于 2001-11-14 15:38:08 得分 0
只要能解决问题就行了!那么累的干嘛呀。
呵呵……Top
7 楼uguess(天地间,有我在行走!)回复于 2001-11-17 12:23:22 得分 0
老哥,你的分还在路上么?
Top
8 楼xiaoxiaomuyu(小小木鱼)回复于 2001-11-17 18:13:34 得分 0
只要用Shell "RUNDLL.EXE user,exitwindows"在98下可以安全关机Top
9 楼geoffrey9043(鑫鑫)回复于 2001-11-17 19:17:20 得分 0
shell "Rundll32 user32.dll,EXITWINDOWS"(我一直用它)
Top
10 楼bluesky35(蓝天)回复于 2001-11-17 22:27:17 得分 0
ExitWindowsEx(0,0)就可以了,参数只是一个16进制的值。Top
11 楼Kevinwong(风子)回复于 2001-11-18 12:28:56 得分 0
shell "rundll krnl386.exe,exitkernel"
这个好像暴力一点,对NT\2000没用.
NT\2000 的在楼下.....Top
12 楼Kevinwong(风子)回复于 2001-11-18 12:31:19 得分 10
强制一个本地或远程NT系统关闭 (这麽全的很难找噢,分怎麽加...)
在Windows NT下,你能强制本地或远程机器定时关闭。这段代码将告诉你怎么做。你能指定系统关闭前的等待时间(0代表立即关闭),关闭进程的优先级(决定是否允许保存未完成的工作)和机器是否要重新启动。
开始一个新的Project,加入一个module,然后加入一下代码:
'判断系统是否为NT:
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128 ' Maintenance string for PSS usage
End Type
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Private Const VER_PLATFORM_WIN32_NT = 2
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VER_PLATFORM_WIN32s = 0
'报告API错误:
Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000
Private Const FORMAT_MESSAGE_FROM_HMODULE = &H800
Private Const FORMAT_MESSAGE_FROM_STRING = &H400
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
' =====================================================================
' NT Only
Private Type LARGE_INTEGER
LowPart As Long
HighPart As Long
End Type
Private Type LUID
LowPart As Long
HighPart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
pLuid As LUID
Attributes As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
Privileges(0 To 0) As LUID_AND_ATTRIBUTES
End Type
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, TokenInformationClass As Integer, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Const SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
Private Const SE_PRIVILEGE_ENABLED = &H2
Private Const READ_CONTROL = &H20000
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const STANDARD_RIGHTS_EXECUTE = (READ_CONTROL)
Private Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Private Const TOKEN_ASSIGN_PRIMARY = &H1
Private Const TOKEN_DUPLICATE = (&H2)
Private Const TOKEN_IMPERSONATE = (&H4)
Private Const TOKEN_QUERY = (&H8)
Private Const TOKEN_QUERY_SOURCE = (&H10)
Private Const TOKEN_ADJUST_PRIVILEGES = (&H20)
Private Const TOKEN_ADJUST_GROUPS = (&H40)
Private Const TOKEN_ADJUST_DEFAULT = (&H80)
Private Const TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
TOKEN_ASSIGN_PRIMARY Or _
TOKEN_DUPLICATE Or _
TOKEN_IMPERSONATE Or _
TOKEN_QUERY Or _
TOKEN_QUERY_SOURCE Or _
TOKEN_ADJUST_PRIVILEGES Or _
TOKEN_ADJUST_GROUPS Or _
TOKEN_ADJUST_DEFAULT)
Private Const TOKEN_READ = (STANDARD_RIGHTS_READ Or TOKEN_QUERY)
Private Const TOKEN_WRITE = (STANDARD_RIGHTS_WRITE Or _
TOKEN_ADJUST_PRIVILEGES Or _
TOKEN_ADJUST_GROUPS Or _
TOKEN_ADJUST_DEFAULT)
Private Const TOKEN_EXECUTE = (STANDARD_RIGHTS_EXECUTE)
Private Const TokenDefaultDacl = 6
Private Const TokenGroups = 2
Private Const TokenImpersonationLevel = 9
Private Const TokenOwner = 4
Private Const TokenPrimaryGroup = 5
Private Const TokenPrivileges = 3
Private Const TokenSource = 7
Private Const TokenStatistics = 10
Private Const TokenType = 8
Private Const TokenUser = 1
Private Declare Function InitiateSystemShutdown Lib "advapi32.dll" Alias "InitiateSystemShutdownA" (ByVal lpMachineName As String, ByVal lpMessage As String, ByVal dwTimeout As Long, ByVal bForceAppsClosed As Long, ByVal bRebootAfterShutdown As Long) As Long
Private Declare Function AbortSystemShutdown Lib "advapi32.dll" Alias "AbortSystemShutdownA" (ByVal lpMachineName As String) As Long
' ================================================================
Public Function WinError(ByVal lLastDLLError As Long) As String
Dim sBuff As String
Dim lCount As Long
'返回与LastDLLError关联的错误消息:
sBuff = String$(256, 0)
lCount = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, _
0, lLastDLLError, 0&, sBuff, Len(sBuff), ByVal 0)
If lCount Then
WinError = Left$(sBuff, lCount)
End If
End Function
Public Function IsNT() As Boolean
Static bOnce As Boolean
Static bValue As Boolean
'返回系统是否为NT:
If Not (bOnce) Then
Dim tVI As OSVERSIONINFO
tVI.dwOSVersionInfoSize = Len(tVI)
If (GetVersionEx(tVI) <> 0) Then
bValue = (tVI.dwPlatformId = VER_PLATFORM_WIN32_NT)
bOnce = True
End If
End If
IsNT = bValue
End Function
Private Function NTEnableShutDown(ByRef sMsg As String) As Boolean
Dim tLUID As LUID
Dim hProcess As Long
Dim hToken As Long
Dim tTP As TOKEN_PRIVILEGES, tTPOld As TOKEN_PRIVILEGES
Dim lTpOld As Long
Dim lR As Long
'在NT下,我们必须给试图关闭系统的进程SE_SHUTDOWN_NAME特权
'否则,所有企图关闭系统的调用都会无效!
'寻找Shoudown特权令牌的LUID:
lR = LookupPrivilegeValue(vbNullString, SE_SHUTDOWN_NAME, tLUID)
'如果我们找到了
If (lR <> 0) Then
'取得当前进程的句柄:
hProcess = GetCurrentProcess()
If (hProcess <> 0) Then
'打开令牌来Adjust和Query(用户可能没有权限)
lR = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken)
If (lR <> 0) Then
'好,我们现在可以调整Shutdown特权了:
With tTP
.PrivilegeCount = 1
With .Privileges(0)
.Attributes = SE_PRIVILEGE_ENABLED
.pLuid.HighPart = tLUID.HighPart
.pLuid.LowPart = tLUID.LowPart
End With
End With
'现在允许这个进程关闭系统:
lR = AdjustTokenPrivileges(hToken, 0, tTP, Len(tTP), tTPOld, lTpOld)
If (lR <> 0) Then
NTEnableShutDown = True
Else
Err.Raise eeSSDErrorBase + 6, App.EXEName & ".mShutDown", "不能shutdown:你没有关闭本系统的权限。[" & WinError(Err.LastDllError) & "]"
End If
'记得用完后关闭这个句柄:
CloseHandle hToken
Else
Err.Raise eeSSDErrorBase + 6, App.EXEName & ".mShutDown", "不能shutdown:你没有关闭本系统的权限。[" & WinError(Err.LastDllError) & "]"
End If
Else
Err.Raise eeSSDErrorBase + 5, App.EXEName & ".mShutDown", "不能shutdown:不能终止当前进程。[" & WinError(Err.LastDllError) & "]"
End If
Else
Err.Raise eeSSDErrorBase + 4, App.EXEName & ".mShutDown", "不能shutdown:找不到SE_SHUTDOWN_NAME特权值。[" & WinError(Err.LastDllError) & "]"
End If
End Function
Public Function NTForceTimedShutdown( _
Optional ByVal lTimeOut As Long = -1, _
Optional ByVal sMsg As String = "", _
Optional ByVal sMachineNetworkName As String = vbNullString, _
Optional ByVal bForceAppsToClose As Boolean = False, _
Optional ByVal bReboot As Boolean = False _
) As Boolean
Dim lR As Long
If IsNT Then
'如果我们在NT下,确信我们已经给了这个进程关闭系统的特权:
If Not (NTEnableShutDown(sMsg)) Then
Exit Function
End If
'这是定时关闭系统的代码:
lR = InitiateSystemShutdown(sMachineNetworkName, sMsg, lTimeOut, bForceAppsToClose, bReboot)
If (lR = 0) Then
Err.Raise eeSSDErrorBase + 2, App.EXEName & ".mShutDown", "InitiateSystemShutdown failed: " & WinError(Err.LastDllError)
End If
Else
Err.Raise eeSSDErrorBase + 1, App.EXEName & ".mShutDown", "函数仅在Windows NT下有效。"
End If
End Function
Public Function NTAbortTimedShutdown(Optional ByVal sMachineNetworkName As String = vbNullString)
AbortSystemShutdown sMachineNetworkName
End Function
为了试验一次shutdown,在窗体上放两个Command按钮和一个Text,然后粘贴一下代码。注意,你必须在运行前保存你的工作,因为Shutdown也将关闭VB且不会给你任何有关保存的询问!
点击Command1,它根据Text里的值开始一次定时关机。要终止Shutdown,点Command2。
Private Sub Command1_Click()
If (MsgBox("你确定要强制定时关机吗?", vbYesNo Or vbQuestion) = vbYes) Then
NTForceTimedShutdown CLng(Text1.Text), "系统将在" & Text1.Text & "秒后关闭..."
End If
End Sub
Private Sub Command2_Click()
NTAbortTimedShutdown
End Sub
Private Sub Form_Load()
Text1.Text = 60
End Sub Top




