Search code examples
c#.netwmishutdown

WMI to reboot remote machine


I found this code on an old thread to shutdown the local machine:

using System.Management;

void Shutdown()
{
    ManagementBaseObject mboShutdown = null;
    ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
    mcWin32.Get();

    // You can't shutdown without security privileges
    mcWin32.Scope.Options.EnablePrivileges = true;
    ManagementBaseObject mboShutdownParams =
             mcWin32.GetMethodParameters("Win32Shutdown");

    // Flag 1 means we want to shut down the system. Use "2" to reboot.
    mboShutdownParams["Flags"] = "1";
    mboShutdownParams["Reserved"] = "0";
    foreach (ManagementObject manObj in mcWin32.GetInstances())
    {
        mboShutdown = manObj.InvokeMethod("Win32Shutdown", 
                                       mboShutdownParams, null);
    }
}

Is it possible to use a similar WMI method to reboot flag "2" a remote machine, for which i only have machine name, not IPaddress.

EDIT: I currently have:

SearchResultCollection allMachinesCollected = machineSearch.FindAll();
Methods myMethods = new Methods();
string pcName;
ArrayList allComputers = new ArrayList();
foreach (SearchResult oneMachine in allMachinesCollected)
{
    //pcName = oneMachine.Properties.PropertyNames.ToString();
    pcName = oneMachine.Properties["name"][0].ToString();
    allComputers.Add(pcName);
    MessageBox.Show(pcName + "has been sent the restart command.");
    Process.Start("shutdown.exe", "-r -f -t 0 -m \\" + pcName);
}

but this doesn't work, and I would prefer WMI going forward.


Solution

  • To address WMI queries to a remote computer, you simply specify that computer's name (or IP address) in the ManagementScope object.

    I'm not well up in C#, but here's an example I came up with using MSDN and WMI Code Creator (which is, by the way, an excellent tool for generating WMI code, and supports C# among others). Hope this code will give you the idea.

    (Disclaimer: This code is untested.)

    using System;
    using System.Management;
    ...
    
    void Shutdown()
    {
        try
        {
            const string computerName = "COMPUTER"; // computer name or IP address
    
            ConnectionOptions options = new ConnectionOptions();
            options.EnablePrivileges = true;
            // To connect to the remote computer using a different account, specify these values:
            // options.Username = "USERNAME";
            // options.Password = "PASSWORD";
            // options.Authority = "ntlmdomain:DOMAIN";
    
            ManagementScope scope = new ManagementScope(
              "\\\\" + computerName +  "\\root\\CIMV2", options);
            scope.Connect();
    
            SelectQuery query = new SelectQuery("Win32_OperatingSystem");
            ManagementObjectSearcher searcher = 
                new ManagementObjectSearcher(scope, query);
    
            foreach (ManagementObject os in searcher.Get())
            {
                // Obtain in-parameters for the method
                ManagementBaseObject inParams = 
                    os.GetMethodParameters("Win32Shutdown");
    
                // Add the input parameters.
                inParams["Flags"] =  2;
    
                // Execute the method and obtain the return values.
                ManagementBaseObject outParams = 
                    os.InvokeMethod("Win32Shutdown", inParams, null);
            }
        }
        catch(ManagementException err)
        {
            MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message);
        }
        catch(System.UnauthorizedAccessException unauthorizedErr)
        {
            MessageBox.Show("Connection error (user name or password might be incorrect): " + unauthorizedErr.Message);
        }
    }