ProblemYou want to programmatically restart the user's workstation. SolutionSample 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:
DiscussionCreate 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 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. |