我用API函数ExitWindowsEx (),实现在windows2000 SERVER下关机。
但是参数值无论怎么更换,都不能关机,只是把系统注销了!
请问:(1)这个函数应该怎么调用才能实现关机或者重启系统?
     (2)如果这个API函数不能在WINDOWS2000 SERVER系统下实现上述功能,是否在这个系统环境下还有其他的API函数?如果有是什么?怎么调用它?

解决方案 »

  1.   

    Option Explicit Private Const EWX_LogOff As Long = 0 
    Private Const EWX_SHUTDOWN As Long = 1 
    Private Const EWX_REBOOT As Long = 2 
    Private Const EWX_FORCE As Long = 4 
    Private Const EWX_POWEROFF As Long = 8 
    Private Const mlngWindows95 = 0 
    Private Const mlngWindowsNT = 1 
    Public glngWhichWindows32 As Long Private Declare Function GetVersion Lib "kernel32" () As Long Private Type LUID 
     UsedPart As Long 
     IgnoredForNowHigh32BitPart As Long 
    End Type Private Type LUID_AND_ATTRIBUTES 
     TheLuid As LUID 
     Attributes As Long 
    End Type Private Type TOKEN_PRIVILEGES 
     PrivilegeCount As Long 
     TheLuid As LUID 
     Attributes As Long 
    End Type 
        
    Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long 
    Private Declare Function GetLastError Lib "kernel32" () 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 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 LookupPrivilegevalue Lib "advapi32.dll" Alias "LookupPrivilegevalueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long 
    Private Declare Sub SetLastError Lib "kernel32" (ByVal dwErrCode As Long) Private Sub AdjustToken() 
    '******************************************************************** 
    '* This procedure sets the proper privileges to allow a log off or a 
    '* shut down to occur under Windows NT. 
    '******************************************************************** 
     Const TOKEN_ADJUST_PRIVILEGES = &H20 
     Const TOKEN_QUERY = &H8 
     Const SE_PRIVILEGE_ENABLED = &H2 

     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 

     SetLastError 0 
     hdlProcessHandle = GetCurrentProcess() 
     If GetLastError <> 0 Then 
       MsgBox "GetCurrentProcess error==" & GetLastError 
     End If 
     OpenProcessToken hdlProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle 
     If GetLastError <> 0 Then 
       MsgBox "OpenProcessToken error==" & GetLastError 
     End If 
     LookupPrivilegevalue "", "SeShutdownPrivilege", tmpLuid 
     If GetLastError <> 0 Then 
        MsgBox "LookupPrivilegevalue error==" & GetLastError 
     End If 
     tkp.PrivilegeCount = 1    ' One privilege to set 
     tkp.TheLuid = tmpLuid 
     tkp.Attributes = SE_PRIVILEGE_ENABLED 
     AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded 
     If GetLastError <> 0 Then 
       MsgBox "AdjustTokenPrivileges error==" & GetLastError 
     End If 
    End Sub Private Sub cmdLogoff_Click() 
     ExitWindowsEx (EWX_LogOff), &HFFFF 
     MsgBox "ExitWindowsEx's GetLastError " & GetLastError 
    End Sub Private Sub cmdForceLogoff_Click() 
     ExitWindowsEx (EWX_LogOff Or EWX_FORCE), &HFFFF 
     MsgBox "ExitWindowsEx's GetLastError " & GetLastError 
    End Sub Private Sub cmdShutdown_Click() 
     If glngWhichWindows32 = mlngWindowsNT Then 
       AdjustToken 
       MsgBox "Post-AdjustToken GetLastError " & GetLastError 
     End If 
     ExitWindowsEx (EWX_SHUTDOWN), &HFFFF 
     MsgBox "ExitWindowsEx's GetLastError " & GetLastError 
    End Sub Private Sub cmdForceShutdown_Click() 
     If glngWhichWindows32 = mlngWindowsNT Then 
       AdjustToken 
       MsgBox "Post-AdjustToken GetLastError " & GetLastError 
     End If 
     ExitWindowsEx (EWX_SHUTDOWN Or EWX_FORCE Or EWX_POWEROFF ), &HFFFF
     MsgBox "ExitWindowsEx's GetLastError " & GetLastError 
    End Sub Private Sub FORM_Load() 
    '******************************************************************** 
    '* When the project starts, check the operating system used by 
    '* calling the GetVersion function. 
    '******************************************************************** 
     Dim lngVersion As Long 
     lngVersion = GetVersion() 
     If ((lngVersion And &H80000000) = 0) Then 
       glngWhichWindows32 = mlngWindowsNT 
       MsgBox "Running Windows NT" 
     Else 
       glngWhichWindows32 = mlngWindows95 
        MsgBox "Running Windows 95" 
     End If 
    End Sub 
      

  2.   

    重新启动Windows 2000/NT系统 Reboots a Windows 2000 PC. Many examples shell to the kernel and just kill the PC. This does it properly and takes into account a user privilages. 'API Calls used for RebootPCPrivate Const TOKEN_ADJUST_PRIVILEGES = &H20
    Private Const TOKEN_QUERY = &H8
    Private Const SE_PRIVILEGE_ENABLED = &H2
    Private Const EWX_SHUTDOWN As Long = 1
    Private Const EWX_FORCE As Long = 4
    Private Const EWX_REBOOT = 2
    Private Type LUID
     UsedPart As Long
     IgnoredForNowHigh32BitPart As Long
    End TypePrivate Type TOKEN_PRIVILEGES
     PrivilegeCount As Long
     TheLuid As LUID
     Attributes As Long
    End TypePrivate Declare Function ExitWindowsEx Lib "user32" (ByVal dwOptions As Long, ByVal dwReserved As Long) As Long
    Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
    Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
    Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
    Private Declare Function AdjustTokenPrivileges Lib "advapi32" (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
    Sub RebootPC()
     On Local Error GoTo RebootPC_ErrorHandler
     Const csProcName = "RebootPC"
     
     Dim hProcessHandle As Long
     Dim hTokenHandle As Long
     Dim tmpLuid As LUID
     Dim tkpNew As TOKEN_PRIVILEGES
     Dim tkpPrevious As TOKEN_PRIVILEGES
     Dim lBufferNeeded As Long hProcessHandle = GetCurrentProcess()
     Call OpenProcessToken(hProcessHandle, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hTokenHandle)' Get the LUID for the shutdown privilege
     Call LookupPrivilegeValue("", "SeShutdownPrivilege", tmpLuid) tkpNew.PrivilegeCount = 1 ' One privilege to set
     tkpNew.TheLuid = tmpLuid
     tkpNew.Attributes = SE_PRIVILEGE_ENABLED' Enable the shutdown privilege in the access token of this process.
     lBufferNeeded = 0
     Call AdjustTokenPrivileges(hTokenHandle, False, tkpNew, Len(tkpPrevious), tkpPrevious, lBufferNeeded)' Force a Reboot (no option to save files to cancel out)
     Call ExitWindowsEx(EWX_FORCE Or EWX_REBOOT, &HFFFF) Exit Sub
    RebootPC_ErrorHandler:
     Call RaiseError(csModName, csProcName, Err.Number, Err.Description)
    End Sub
      

  3.   


    Public Declare Function ExitWindows Lib "user32" (ByVal dwReserved As Long, ByVal uReturnCode As Long) As Long
    Public Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
    Public Declare Function GetCurrentProcess Lib "kernel32" () As Long
    Public Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
    Public 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
    Public Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As LongPublic Const ANYSIZE_ARRAY = 1
    Public Const TOKEN_ADJUST_PRIVILEGES = &H20
    Public Const TOKEN_QUERY = &H8
    Public Const SE_PRIVILEGE_ENABLED = &H2
    Public Type LUID
      LowPart As Long
      HighPart As Long
    End Type
    Public Type LUID_AND_ATTRIBUTES
      pLuid As LUID
      Attributes As Long
    End Type
    Public Type TOKEN_PRIVILEGES
      PrivilegeCount As Long
      Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
    End Type
    Public Type LARGE_INTEGER
      LowPart As Long
      HighPart As Long
    End TypePrivate Sub AdjustTokenPrivilegesFor2000() '使NT关机的副程序
    On Error Resume Next
      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
      
      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 SubPrivate Sub CloseComputer()
    On Error Resume Next
                Call AdjustTokenPrivilegesFor2000
                ' ExitWindowsEx 8, 0 '强制关机
                ExitWindowsEx 1, 0 '提示保存,关机
                EndEnd Sub
      

  4.   

    这个函数可以实现你的功能要求,我用他可以关掉2000 xp 2003server,