2010-05-27 150 views
12

我发现这个代码在一个古老的线程来关闭本地计算机:WMI重新启动远程计算机

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

是否有可能使用类似的WMI方法重新启动标志“2”的远程机器,为此,我只有机器名称,而不是IP地址。

编辑:我目前有:

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

但是,这并不工作,我宁愿WMI前进。

回答

14

要将WMI查询发送到远程计算机,只需在ManagementScope对象中指定该计算机的名称(或IP地址)即可。

我在C#中不是很好,但是这里有一个例子,我想到了使用MSDN和WMI Code Creator(顺便说一句,这是生成WMI代码的优秀工具,并且支持C#等)。希望这段代码能给你这个想法。

免责声明:此代码是未经测试)

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

作为参考,“标志”的价值2是什么把这个关机请求变成重新启动。完整的标志列表在这里:https://msdn.microsoft.com/en-us/library/aa394058(v=vs.85).aspx – Ceilingfish 2015-10-26 16:01:05

4

我也遇到了麻烦。 WMI可能会误导类和对象的方法。我的解决办法是重新启动与C#和WMI网络上的主机,但很容易简化为本地机器:

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

我发现这种方法适用于Azure虚拟机,只要机器是相同的VPN。接受的答案没有出于某种原因。 – user3841460 2016-10-11 19:51:22

0

这会像沙姆沙伊赫

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