FAQ по Visual Basic

Содержание / Windows API Поиск | Далее

§ 5.15. Как можно выключить или перезагрузить компьютер?

Для выполнения этих операций существует функция ExitWindowsEx:

Declare Function ExitWindowsEx Lib "user32" _
    (ByVal uFlags As Long, _
    ByVal dwReason As Long) As Long

Первый параметр задает тип выполняемого действия. Эти действия перечислены ниже:

' завершение сеанса пользователя
Public Const EWX_LOGOFF      = &H0&
' шатдаун компьютера
Public Const EWX_SHUTDOWN    = &H1&
' перезагрузка компьютера
Public Const EWX_REBOOT      = &H2&
' выключение компьютера (ATX)
Public Const EWX_POWEROFF    = &H8&

' флаг принудительного выполнения операции
Public Const EWX_FORCE       = &H4&
' флаг принудительного выполнения при зависании
Public Const EWX_FORCEIFHUNG = &H10&

Первые 4 константы задают конкретное действие. Остальные параметры — битовые модификаторы и их можно комбинировать.

Флажок EWX_FORCE заставляет выполнить действие, не обращая внимания на протесты приложений (скажем, если в Word находятся несохраненные данные, то без флага EWX_FORCE действие не будет выполнено, пока пользователь не ответит на запрос Word'а).

Флаг EWX_FORCEIFHUNG позволяет проигнорировать зависшие приложения.

Второй параметр во всех системах до Windows XP являлся зарезервированным, а теперь ему нашли применение для указания причины, по которой нужно завершить сеанс работы системы.

Небольшой пример. Перезагрузим компьютер с флагом EWX_FORCE:

    ExitWindowsEx EWX_REBOOT Or EWX_FORCE, 0

Теперь перехожу к одному довольно интересному вопросу. Дело в том, что спокойно вызывать эту функцию можно только под Windows 9x; для NT же требуется сначала получить привилегию на это.

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 Function AdjustTokenPrivileges _
    Lib "advapi32.dll" _
    (ByVal TokenHandle As Long, _
    ByVal DisableAllPrivileges As Long, _
    NewState As TOKEN_PRIVILEGES, _
    ByVal BufferLength As Long, _
    PreviousState As Any, _
    ReturnLength As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long

Private Declare Function ExitWindowsEx Lib "user32" _
    (ByVal uFlags As Long, _
    ByVal dwReason As Long) As Long

Private Declare Function GetVersionEx Lib "kernel32" _
    Alias "GetVersionExA" _
    (lpVersionInformation As OSVERSIONINFO) As Long

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) As LUID_AND_ATTRIBUTES
End Type

Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type

Const TOKEN_QUERY = &H8
Const TOKEN_ADJUST_PRIVILEGES = &H20

Const SE_SHUTDOWN_NAME = "SeShutdownPrivilege"

Const SE_PRIVILEGE_ENABLED = &H2

Const VER_PLATFORM_WIN32_NT = 2

Enum enmShutdownMode
    smLogoff = 0
    smShutdown = 1
    smReboot = 2
    smPoweroff = 8
    
    smForce = 4
    smForceIfHung = 16
End Enum

Public Function Shutdown( _
        ByVal Mode As enmShutdownMode, _
        Optional ByVal Reason As Long = 0 _
        ) As Boolean

Dim hToken As Long
Dim tp As TOKEN_PRIVILEGES
Dim osvi As OSVERSIONINFO
osvi.dwOSVersionInfoSize = Len(osvi)

GetVersionEx osvi
If osvi.dwPlatformId = VER_PLATFORM_WIN32_NT Then
    If OpenProcessToken(GetCurrentProcess(), _
        TOKEN_ADJUST_PRIVILEGES Or _
        TOKEN_QUERY, hToken) _
    Then
        LookupPrivilegeValue vbNullString, _
            SE_SHUTDOWN_NAME, tp.Privileges(0).pLuid

        tp.PrivilegeCount = 1
        tp.Privileges(0).Attributes = _
            SE_PRIVILEGE_ENABLED

        AdjustTokenPrivileges hToken, False, tp, _
            0, ByVal 0&, 0

        CloseHandle hToken
    End If
End If

Shutdown = CBool(ExitWindowsEx(Mode, Reason))
End Function

Авторы:
Александр Щербаков, Master

Предыдущий раздел Следующий раздел

© 2004. При цитировании, пожалуйста, не забудьте поставить ссылку на оригинальную страницу.