Aquí os dejo un mini-programa de reinicio y apagado que es lo más potente que he encontrado para VB. Si esto no apaga el PC en un rato, mejor que uses el botón.
Adquiere prioridad máxima al iniciarse, permite forzar el apagado y adquiere privilegios de apagado para un cierre más seguro.
Para simplificar lo he hecho sin botones ni nada. Vá por línea de comandos. Es lo más rápido para posibles bloqueos.
Lo mejor es poner el ejecutable en la carpeta de Windows y para usarlo abrir el menú de inicio/ejecutar y teclear ahí la orden. P.ej.: Apaga R
También puedes crear un acceso directo en el escritorio u otro sitio y modificar las propiedades para que esté listo para un reinicio forzado, por si hace falta.
Al ejecutarlo sin parámetros muestra la ayuda, para evirar reinicios no deseados y por si olvido los parámetros.
Código vb:
Ver originalOption Explicit
Const EWX_SHUTDOWN As Long = 1
Const EWX_REBOOT = 2
Const EWX_FORCE As Long = 4
Const EWX_POWEROFF As Long = 8
Private Type LUID
UsedPart As Long
IgnoredForNowHigh32BitPart As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
TheLuid As LUID
Attributes As Long
End Type
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
Private Declare Function ExitWindowsEx Lib "user32" (ByVal _
dwOptions As Long, ByVal dwReserved As Long) As Long
Private Declare Function SetPriorityClass Lib "kernel32" (ByVal hProcess As Long, ByVal dwPriorityclass As Long) As Long
Sub ConsiguePrivilegios()
Const EWX_SHUTDOWN As Long = 1
Const EWX_FORCE As Long = 4
Const EWX_POWEROFF As Long = 8
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
hdlProcessHandle = GetCurrentProcess()
OpenProcessToken hdlProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle
LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
tkp.PrivilegeCount = 1
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded
End Sub
Sub Reiniciar(Forzar As Boolean)
If Forzar = True Then
ExitWindowsEx EWX_SHUTDOWN + EWX_REBOOT + EWX_FORCE, 0
Else
ExitWindowsEx EWX_SHUTDOWN + EWX_REBOOT, 0
End If
End Sub
Sub Apagar(Forzar As Boolean)
If Forzar = True Then
ExitWindowsEx EWX_SHUTDOWN + EWX_POWEROFF + EWX_FORCE, 0
Else
ExitWindowsEx EWX_SHUTDOWN + EWX_POWEROFF, 0
End If
End Sub
Private Sub Form_Initialize()
Const REALTIME_PRIORITY_CLASS = &H100
Dim sCmd As String
Dim ForzarCierre As Boolean
SetPriorityClass GetCurrentProcess, REALTIME_PRIORITY_CLASS
ConsiguePrivilegios
sCmd = UCase$(Trim$(Command))
If InStr(1, sCmd, "F") Then ForzarCierre = True
If InStr(1, sCmd, "A") Then
Apagar ForzarCierre
ElseIf InStr(1, sCmd, "R") Then
Reiniciar ForzarCierre
Else
MsgBox _
" Apagar el equipo." & vbCrLf & _
App.EXEName & " A" & vbCrLf & _
" Apagar el equipo y forzar el cierre de los programas." & vbCrLf & _
App.EXEName & " A F" & vbCrLf & _
" Reiniciar el equipo." & vbCrLf & _
App.EXEName & " R" & vbCrLf & _
" Reiniciar el equipo y forzar el cierre de los programas." & vbCrLf & _
App.EXEName & " R F"
End If
End
End Sub
Por supuesto, también podeis modificarlo y que funcione como cada cual quiera que lo haga.
Espero que sea útil.
Saludos.