2010-05-27 3 views
12

J'ai trouvé ce code sur un vieux fil à l'arrêt de la machine locale:WMI pour redémarrer la machine distante

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); 
    } 
} 

Est-il possible d'utiliser une méthode WMI similaire pour redémarrer flag « 2 » une machine distante, pour laquelle J'ai seulement le nom de la machine, pas IPaddress.

EDIT: J'ai actuellement:

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); 
} 

mais cela ne fonctionne pas, et je préférerais WMI aller de l'avant.

Répondre

14

Pour adresser des requêtes WMI à un ordinateur distant, il vous suffit de spécifier le nom (ou l'adresse IP) de cet ordinateur dans l'objet ManagementScope. Je ne suis pas très bon en C#, mais voici un exemple que j'ai trouvé en utilisant MSDN et WMI Code Creator (qui est, en passant, un excellent outil pour générer du code WMI, et supporte C# parmi d'autres). J'espère que ce code vous donnera l'idée.

(Avertissement:. Ce code est non testé)

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); 
    } 
} 
+2

Pour référence, la valeur « Flags » de 2 est ce qui transforme cette demande d'arrêt en un redémarrage. La liste complète des drapeaux ici: https://msdn.microsoft.com/en-us/library/aa394058(v=vs.85).aspx – Ceilingfish

4

J'ai eu des problèmes avec cela aussi. WMI peut être trompeur avec des méthodes pour les classes et les objets. Ma solution est pour le redémarrage d'un hôte sur le réseau avec C# et WMI, mais est facilement simplifiée pour la machine locale:

private void rebootHost(string hostName) 
{ 
    string adsiPath = string.Format(@"\\{0}\root\cimv2", hostName); 
    ManagementScope scope = new ManagementScope(adsiPath); 
    // I've seen this, but I found not necessary: 
    // scope.Options.EnablePrivileges = true; 
    ManagementPath osPath = new ManagementPath("Win32_OperatingSystem"); 
    ManagementClass os = new ManagementClass(scope, osPath, null); 

    ManagementObjectCollection instances; 
    try 
    { 
     instances = os.GetInstances(); 
    } 
    catch (UnauthorizedAccessException exception) 
    { 
     throw new MyException("Not permitted to reboot the host: " + hostName, exception); 
    } 
    catch (COMException exception) 
    { 
     if (exception.ErrorCode == -2147023174) 
     { 
      throw new MyException("Could not reach the target host: " + hostName, exception); 
     } 
     throw; // Unhandled 
    } 
    foreach (ManagementObject instance in instances) 
    { 
     object result = instance.InvokeMethod("Reboot", new object[] { }); 
     uint returnValue = (uint)result; 

     if (returnValue != 0) 
     { 
      throw new MyException("Failed to reboot host: " + hostName); 
     } 
    } 
} 
+0

J'ai trouvé cette méthode fonctionne sur Azure VM tant que la machine est sur le même VPN. La réponse acceptée ne l'a pas fait pour une raison quelconque. – user3841460

0

cela fonctionnera comme charm

gwmi win32_operatingsystem -ComputerName xxxxxxxxxxxx | Invoke-WmiMethod -Name reboot 
Questions connexes