One of the biggest complaints I hear from administrators concerning Windows NT is the supposed lack of remote administration tools. Paramount among these is the ability to shut down an NT box remotely. While I feel that shutting down a well-running server is synonymous to skydiving out of a perfectly good aircraft, sometimes problems occur and you need to bail out. With Visual Basic and some simple API calls, you can be assured of a safe landing.
The Windows NT API includes a function called InititateSystemShutdown. Simply add this function to the General Declarations section of your Visual Basic project like so:
Private Declare Function InitiateSystemShutdown Lib “advapi32.dll”Alias “InitiateSystemShutdownA” (ByVal lpMachineName As String, ByVal lpMessage As String, ByVal dwTimeout As Long, ByVal bForceAppsClosed As Long, ByVal bRebootAfterShutdown As Long) As Long
Let’s look at each of the required parameters and what they mean. lpMachineName is simply the name of the machine you want to shut down. If you pass it a Null or a blank string, it’s assumed that you want to shut down the local machine. To display a message on the remote machine, use lpMessage. Doing so allows you to inform a potential user of what is going on and why the system is shutting down.
The dwTimeout parameter is the time, in seconds, until the system shuts down. If you don’t specify a value here, the remote system will shut down immediately. The last two parameters, bForceAppsClosed and bRebootAfterShutdown, act like Boolean values, meaning they are either true or false, 1 or 0. Their names are self explanatory, but let me give you one little warning. BForceAppsClosed, if called with a low timeout value, may not give a user on the remote machine time to save his or her work. It will simply force the applications closed, resulting in the loss of unsaved changes.
Your success in using this function depends on a couple of variables. First is security. You must have rights to shut down the machine. If you’re an administrator on the machine, this should be no problem. Your second problem is finding the remote machine on the network. The protocols and services bound to your network adapter decide the best method for calling the remote machine. If you have NetBIOS enabled, you can use the NetBIOS name. Otherwise, you have to use something else—either an IP address or, preferably, a fully qualified domain name (i.e., machinename.somedomain.com). A failure of either one of these will cause the function call to fail.
If you’re successful in calling the function (the return value is something other than 0), a window will pop up on the remote machine informing the user (if any) that the system is being shut down. It will also indicate who called for the shutdown, show a timer counting down to shutdown, and display the value of lpMessage. The user will not have the option of stopping the shutdown.
What if you made a mistake and started a shutdown of the wrong machine? You didn’t think we’d let you jump without a parachute, did you? The Windows NT API provides for this possibility with another, even easier-to-use function: AbortSystemShutdown.
Add this function to the General Declarations section as we did with the InitiateSystemShutdown function:
Private Declare Function AbortSystemShutdown Lib “advapi32.dll” Alias “AbortSystemShutdownA” (ByVal lpMachineName As String) As Long
As you can see, it takes only one parameter—the name of the remote machine. Call the function and, if successful, the shutdown on the remote machine stops. The key here is that you have to call AbortSystemShutdown before the dwTimeout value expires; otherwise, it’s too late.
Unfortunately, these functions don’t allow you to do much more than reboot a remote machine. For more options, you’ll have to wait for Windows 2000 or use the Windows Management Interface.
If you’d like to share your opinion, please post a comment below.