Recipe 14.34. Rebooting the System


You want to programmatically restart the user's workstation.


Sample code folder: Chapter 14\ShutdownWindows

With all of the convenience features included in .NET, you would think that there would be a ShutdownWindows() method in some convenient class. But alas, there is nothing like that. To shut down Windows, you must depend on some of the Win32 DLL features. This recipe's sample code lets you exit Windows in one of four ways:

  • By locking the workstation (although this is not really exiting Windows)

  • By logging the current user out of Windows

  • By rebooting the system

  • By shutting down the system


Create a new Windows Forms application. Add four Button controls to Form1, named ActLockWorkstation, ActLogoff, ActReboot, and ActShutdown. Change their Text properties to Lock Workstation, Log off, Reboot, and Shut down, respectively. Then add the following code to the form's code template:

 Private Sub ActLockWorkstation_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles ActLockWorkstation.Click    GetOutOfWindows.ExitViaLockWorkstation( ) End Sub Private Sub ActLogoff_Click(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles ActLogoff.Click    GetOutOfWindows.ExitViaLogoff( ) End Sub Private Sub ActReboot_Click(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles ActReboot.Click    GetOutOfWindows.ExitViaReboot( ) End Sub Private Sub ActShutdown_Click(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles ActShutdown.Click    GetOutOfWindows.ExitViaShutdown( ) End Sub 

Add a new class to your project using the Project Add Class menu command, giving its file the name GetOutOfWindows.vb. Use this code for the class body:

 Public Class GetOutOfWindows    ' ----- Windows constants used in shutdown permissions.    Const SE_PRIVILEGE_ENABLED As Integer = &H2    Const TOKEN_QUERY As Integer = &H8    Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20    Const SE_SHUTDOWN_NAME As String = "SeShutdownPrivilege"    ' ----- Shutdown method flags.    Private Enum ShutdownMethods As Integer       Logoff = 0       Shutdown = 1       Reboot = 6    End Enum    <Runtime.InteropServices.StructLayout( _    Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _    Private Structure TokenPrivileges       Public PrivilegeCount As Integer       Public Luid As Long       Public Attributes As Integer    End Structure    ' ----- External features needed to exit Windows.    Private Declare Ansi Function AdjustTokenPrivileges _       Lib "advapi32.dll" _       (ByVal tokenHandle As IntPtr, _       ByVal disableAllPrivileges As Boolean, _       ByRef newState As TokenPrivileges, _       ByVal bufferLength As Integer, _       ByVal previousState As IntPtr, _       ByVal returnLength As IntPtr) As Boolean    Private Declare Ansi Function ExitWindowsEx _       Lib "user32.dll" _       (ByVal flags As Integer, _       ByVal reason As Integer) As Boolean    Private Declare Ansi Function GetCurrentProcess _       Lib "kernel32.dll" ( ) As IntPtr    Private Declare Ansi Sub LockWorkStation _       Lib "user32.dll" ( )    Private Declare Ansi Function LookupPrivilegeValueA _       Lib "advapi32.dll" _       (ByVal   systemName As String, _       ByVal privilegeName As String, _       ByRef lookupID As Long) As Boolean    Private Declare Ansi Function OpenProcessToken _       Lib "advapi32.dll" _       (ByVal processHandle As IntPtr, _       ByVal desiredAccess As Integer, _       ByRef tokenHandle As IntPtr) As Boolean    Private Shared Sub PerformExit( _          ByVal usingMethod As Integer)       ' ----- Log off, reboot, or shut down the   system.       Dim shutdownPrivileges As TokenPrivileges       Dim processHandle As IntPtr       Dim tokenHandle As IntPtr = IntPtr.Zero       ' ----- Give ourselves the privilege of shutting       '       down the system. First, obtain the token.       processHandle = GetCurrentProcess( )       OpenProcessToken(processHandle, _          TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, tokenHandle)       ' ----- Adjust the token to enable shutdown permissions.       shutdownPrivileges.PrivilegeCount = 1       shutdownPrivileges.Luid = 0       shutdownPrivileges.Attributes = SE_PRIVILEGE_ENABLED       LookupPrivilegeValueA(Nothing, SE_SHUTDOWN_NAME, _          shutdownPrivileges.Luid)       AdjustTokenPrivileges(tokenHandle, False, _          shutdownPrivileges, 0, IntPtr.Zero, IntPtr.Zero)       ' ----- Now shut down the system.       ExitWindowsEx(usingMethod, 0)    End Sub    Public Shared Sub ExitViaLockWorkstation( )       ' ----- Lock the workstation.       LockWorkStation( )    End Sub    Public Shared Sub ExitViaLogoff( )       ' ----- Log off the current user.       PerformExit(ShutdownMethods.Logoff)    End Sub    Public Shared Sub ExitViaReboot( )       ' ----- Reboot the system.       PerformExit(ShutdownMethods.Reboot)    End Sub    Public Shared Sub ExitViaShutdown( )       ' ----- Shut down the system.       PerformExit(ShutdownMethods.Shutdown)    End Sub End Class 

Run the program, and click one of the buttons on the form to take the related shutdown action. But be warned: this program will shut down Windows if you choose anything other than "Lock Workstation." Make sure you save your work before running this program.

Most of this code gets into the heart of the Windows system, and how it really works is beyond the scope of this book (and beyond general human comprehension). But here's the gist of it: before you can shut down Windows, you have to give yourself permission to do so. It must be a safety feature, because if you can give yourself permission, it's really not a matter of security.

Still, if your application runs in a security-limited context imposed by the user or the system administrator, the attempt to shut down the system may fail.

Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400 © 2008-2017.
If you may any questions please contact us: