Shutting the System Down Remotely Example

You'll run into situations in which you need to shut a system down from a remote location. Most people associate this action with servers; the server might reside in a closet and not even include a monitor and keyboard. However, remote shutdown becomes more important for desktop computers on a daily basis. For example, when a user logs in from a remote location, part of the login process could turn the user's desktop computer on and prepare it for use. When the user session ends, it's good practice to shut the computer back down. This action could also occur when a maintenance action takes place. In sum, the uses for a remote shutdown are numerous.

Note This chapter doesn't tell how to shut a system down locally because we've already discussed this issue as part of the message processing information in Chapter 4. See the section "Demonstrating the Windows Message Handler" in Chapter 4 for an example of how you can shut down your system locally. This chapter also shows how to trap and handle shutdown messages—an essential feature for many applications.

From the discussion in Chapter 4, you know that the ExitWindows() and ExitWindowsEx() functions only work on the local computer. If you want to shut down a remote computer, you need to use the InitiateSystemShutdown() or the InitiateSystemShutdownEx() function. The main difference between the latter two functions is that the InitiateSystemShutdownEx() function allows the developer to log a reason for the shutdown in the system log. Before either of these functions will work, however, the remote system has to allow remote shutdowns. In addition, there are a number of Windows bugs that appear in the Platform SDK documentation that will prevent a remote shutdown. For example, Windows 9x will often refuse to shut down after a remote request if the system is locked for some other reason (such as when the screensaver is active).

Now that you have some idea of what the example will do, let's look at the code required to shut down a remote system. Listing 10.3 shows the code we'll use for this example. This source code is incomplete—it leaves out the enumerations we used for the example in Chapter 4. The source on the CD does contain the complete code. You'll find the code in the \Chapter 10\C#\RemoteShutdown and \Chapter 10\VB\RemoteShutdown folders of the source code CD.

Listing 10.3: A Technique to Shut Down a System Remotely

// This function performs the remote shutdown. [DllImport("AdvAPI32.DLL")]

public static extern Boolean InitiateSystemShutdownEx( String lpMachineName, String lpMessage, Int32 dwTimeout, Boolean bForceAppsClosed, Boolean bRebootAfterShutdown, UInt32 dwReason);

private void btnShutdown_Click(object sender, System.EventArgs e) {

// Shut the remote system down. if (!InitiateSystemShutdownEx( txtMachine.Text, txtMessage.Text, Int32.Parse(txtTimeout.Text), ckAppClose.Checked, ckReboot.Checked,

(UInt3 2)ReasonMajor.SHTDN_REASON_MAJOR_OTHER | (UInt3 2)ReasonMinor.SHTDN_REASON_MINOR_MAINTENANCE | (UInt32)ReasonFlag.SHTDN_REASON_FLAG_PLANNED))

// Display an error if not successful. MessageBox.Show("Couldn't Shut Remote System Down", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

else

// Display a success message.

MessageBox.Show("Remote System Shutting Down", "Shutdown Success", MessageBoxButtons.OK, MessageBoxIcon.Information);

As you can see, the InitiateSystemShutdownEx() function code isn't complex and you don't need to perform a lot of setup to use it. However, this example does point out some additional inconsistencies of the Win32 API. Compare this example to the ExitWindowsEx() function in Chapter 4 and you'll see that it's actually easier to use, in some ways, because it doesn't require as many flags and enumerations. Figure 10.7 shows the input dialog box for this example. Notice that it includes options for setting the forced application close and the automatic reboot options.

□Si Remote Shutdown Example

_ n x

Machine Name:

Quit

Shutdown Message:

Shutdown |

| Shutting down for maintenance!

Time to Wait:

|15

V Force Application Close

V Reboot After Shutdown

ugure 10.7: The example application provides inputs for most of the InitiateSystemShutdownEx() features.

If you set the lpMachineName argument to null, the InitiateSystemShutdownEx() function will shut down the local machine instead of a remote machine. However, the only way to do this with a .NET application is to provide an override that includes an IntPtr as the first argument. Using a value of IntPtr.Zero will set the first value to null. Generally, however, you'll want to use ExitWindowsEx() whenever possible for local shutdown because it exits cleanly.

The lpMessage argument displays a message on screen. It's usually a good idea to tell the user why you want to shut the system down. On the other hand, there's no reason to include a message for a server in a closet, so you can set this argument to null.

A final consideration for this example is the bForceAppsClosed. Setting this value to true means that Windows will close without allowing the user to save their data. In the case of a frozen machine or a server, this could actually make it possible for the machine to reboot, albeit with some loss of data. However, you'll normally set this argument to false when rebooting a user machine on the network so the user has time to save their data. Figure 10.8 shows the remote message that the InitiateSystemShutdownEx() function creates.

igure 10.8: The InitiateSystemShutdownEx() function creates a remote message for the user.

Was this article helpful?

0 0

Post a comment