Compartir a través de


Conexión a WMI de forma remota con C #

Al igual que con otros lenguajes, como PowerShell, VBScript o C++, puede usar C# para supervisar de forma remota el hardware y el software en equipos remotos. Las conexiones remotas para código administrado se realizan mediante el espacio de nombres Microsoft.Management.Infrastructure. (Las versiones anteriores de WMI usaban el espacio de nombres System.Management, que se incluye aquí por motivos de integridad).

Nota

System.Management era el espacio de nombres de .NET original que se usaba para acceder a WMI; sin embargo, las API de este espacio de nombres suelen ser más lentas y no se escalan tan bien como sus homólogos más modernos Microsoft.Management.Infrastructure.

 

Para la conexión remota mediante clases en el espacio de nombres Microsoft.Management.Infrastructure se utiliza DCOM como mecanismo remoto subyacente. Las conexiones WMI remotas se deben ajustar a los requisitos de seguridad de DCOM en lo que respecta a la suplantación y la autenticación. De forma predeterminada, un ámbito está enlazado al equipo local y al espacio de nombres del sistema "Root\CIMv2". No obstante, puede cambiar el equipo, el dominio y el espacio de nombres de WMI al que tiene acceso. También puede establecer autoridad, suplantación, credenciales y otras opciones de conexión.

Para conectarse a WMI de forma remota con C# (Microsoft.Management.Infrastructure)

  1. Cree una sesión en la máquina remota con una llamada a CimSession.Create.

    Si va a conectarse a un equipo remoto con las mismas credenciales (dominio y nombre de usuario) con las que ha iniciado sesión, puede especificar el nombre del equipo en la llamada a Create. Una vez que haya devuelto el objeto CimSession, puede realizar la consulta de WMI.

    using Microsoft.Management.Infrastructure;
    ...
    string Namespace = @"root\cimv2";
    string OSQuery = "SELECT * FROM Win32_OperatingSystem";
    CimSession mySession = CimSession.Create("Computer_B");
    IEnumerable<CimInstance> queryInstance = mySession.QueryInstances(Namespace, "WQL", OSQuery);
    

    Para más información sobre cómo realizar consultas de WMI con microsoft.Management.Infrastructure API en C#, consulte Recuperación de datos de instancia o clase de WMI.

  2. Si desea establecer diferentes opciones para la conexión, como credenciales diferentes, niveles de configuración regional o suplantación, debe usar un objeto CimSessionOptions en la llamada a CimSession.Create.

    CimSessionOptions es una clase base para WSManSessionOptions y DComSessionOptions. Puede usar cualquiera de ellas para establecer las opciones en las sesiones de WS-Man y DCOM, respectivamente. En el ejemplo de código siguiente se describe el uso de un objeto DComSessionOptions para establecer el nivel de suplantación en Suplantar.

    string computer = "Computer_B"
    DComSessionOptions DComOptions = new DComSessionOptions();
    DComOptions.Impersonation = ImpersonationType.Impersonate;
    
    CimSession Session = CimSession.Create(computer, DComOptions);
    
  3. Si desea establecer las credenciales de la conexión, deberá crear y agregar un objeto CimCredentials a cimSessionOptions.

    En el ejemplo de código siguiente se describe cómo crear una clase WSManSessionOptions, rellenarla con un objeto CimSessionOptions adecuado y usarla en una llamada a CimSession.Create.

    string computer = “Computer_B”;
    string domain = “Domain1″;
    string username = “User1″;
    
    string plaintextpassword; 
    
    //Retrieve password from the user. 
    //For the complete code, see the sample at the bottom of this topic.
    
    CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default, domain, username, securepassword); 
    
    WSManSessionOptions SessionOptions = new WSManSessionOptions();
    SessionOptions.AddDestinationCredentials(Credentials); 
    
    CimSession Session = CimSession.Create(computer, SessionOptions);
    

    Por lo general, se recomienda no codificar de forma rígida una contraseña en las aplicaciones; como indica el ejemplo de código anterior, siempre que sea posible, intente consultar al usuario la contraseña y almacenarla de forma segura.

WMI está diseñado para supervisar el hardware y el software en equipos remotos. Las conexiones remotas de WMI v1 se realizan mediante el objeto ManagementScope.

Para conectarse a WMI de forma remota con C# (System.Management)

  1. Cree un objeto ManagementScope, con el nombre del equipo y la ruta de acceso de WMI, y conéctese al destino con una llamada a ManagementScope.Connect ().

    Si va a conectarse a un equipo remoto con las mismas credenciales (dominio y nombre de usuario) con las que ha iniciado sesión, solo tiene que especificar la ruta de acceso de WMI. Una vez que se haya conectado, puede realizar la consulta de WMI.

    using System.Management;
    ...
    ManagementScope scope = new ManagementScope("\\\\Computer_B\\root\\cimv2");
    scope.Connect();
    ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
    

    Para más información sobre cómo realizar consultas de WMI con System.Management API en C#, consulte Recuperación de datos de instancia o clase de WMI.

  2. Si se conecta a un equipo remoto en un dominio diferente o usa un nombre de usuario y una contraseña diferentes, debe usar un objeto ConnectionOptions en la llamada a ManagementScope.

    ConnectionOptions contiene propiedades para describir la autenticación, suplantación, nombre de usuario, contraseña y otras opciones de conexión. En el ejemplo de código siguiente se describe el uso de ConnectionOptions para establecer el nivel de suplantación en Suplantar.

    ConnectionOptions options = new ConnectionOptions();
    options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
    
    ManagementScope scope = new ManagementScope("\\\\FullComputerName\\root\\cimv2", options);
    scope.Connect();
    
    ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query);
    

    Por lo general, se recomienda establecer el nivel de suplantación en Suplantar, a menos que sea necesario explícitamente establecerlo en un nivel diferente. Además, intente evitar escribir el nombre y la contraseña en código de C#. (Si es posible, consulte si puede consultar al usuario para proporcionarlos dinámicamente en tiempo de ejecución).

    Para obtener más ejemplos de cómo establecer diferentes propiedades en una conexión de WMI remota, consulte la sección Ejemplos de la página de referencia de ConnectionOptions.

Ejemplo de Microsoft.Management.Infrastructure

En el siguiente ejemplo de código de C#, basado en la siguiente entrada de blog de TechNet, se describe cómo usar CimCredentials y WSManSessionOptions para establecer credenciales en una conexión remota.

using System;
using System.Text;
using System.Threading;
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using System.Security; 

namespace SMAPIQuery
{
    class Program
    {
        static void Main(string[] args)
        { 

            string computer = "Computer_B";
            string domain = "DOMAIN";
            string username = "AdminUserName";


            string plaintextpassword; 

            Console.WriteLine("Enter password:");
            plaintextpassword = Console.ReadLine(); 

            SecureString securepassword = new SecureString();
            foreach (char c in plaintextpassword)
            {
                securepassword.AppendChar(c);
            } 

            // create Credentials
            CimCredential Credentials = new CimCredential(PasswordAuthenticationMechanism.Default, 
                                                          domain, 
                                                          username, 
                                                          securepassword); 

            // create SessionOptions using Credentials
            WSManSessionOptions SessionOptions = new WSManSessionOptions();
            SessionOptions.AddDestinationCredentials(Credentials); 

            // create Session using computer, SessionOptions
            CimSession Session = CimSession.Create(computer, SessionOptions); 

            var allVolumes = Session.QueryInstances(@"root\cimv2", "WQL", "SELECT * FROM Win32_Volume");
            var allPDisks = Session.QueryInstances(@"root\cimv2", "WQL", "SELECT * FROM Win32_DiskDrive"); 

            // Loop through all volumes
            foreach (CimInstance oneVolume in allVolumes)
            {
                // Show volume information

                if (oneVolume.CimInstanceProperties["DriveLetter"].ToString()[0] > ' '  )
                {
                    Console.WriteLine("Volume ‘{0}’ has {1} bytes total, {2} bytes available", 
                                      oneVolume.CimInstanceProperties["DriveLetter"], 
                                      oneVolume.CimInstanceProperties["Size"], 
                                      oneVolume.CimInstanceProperties["SizeRemaining"]);
                }

            } 

            // Loop through all physical disks
            foreach (CimInstance onePDisk in allPDisks)
            {
                // Show physical disk information
                Console.WriteLine("Disk {0} is model {1}, serial number {2}", 
                                  onePDisk.CimInstanceProperties["DeviceId"], 
                                  onePDisk.CimInstanceProperties["Model"].ToString().TrimEnd(), 
                                  onePDisk.CimInstanceProperties["SerialNumber"]);
            } 

            Console.ReadLine();
         }
     }
 }

Ejemplo de System.Management

En el ejemplo de código de C# siguiente se describe una conexión remota general mediante objetos System.Management.

using System;
using System.Management;
public class RemoteConnect 
{
    public static void Main() 
    {
        ConnectionOptions options = new ConnectionOptions();
        options.Impersonation = System.Management.ImpersonationLevel.Impersonate;

        
        ManagementScope scope = new ManagementScope("\\\\FullComputerName\\root\\cimv2", options);
        scope.Connect();

        //Query system for Operating System information
        ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,query);

        ManagementObjectCollection queryCollection = searcher.Get();
        foreach ( ManagementObject m in queryCollection)
        {
            // Display the remote computer information
            Console.WriteLine("Computer Name     : {0}", m["csname"]);
            Console.WriteLine("Windows Directory : {0}", m["WindowsDirectory"]);
            Console.WriteLine("Operating System  : {0}", m["Caption"]);
            Console.WriteLine("Version           : {0}", m["Version"]);
            Console.WriteLine("Manufacturer      : {0}", m["Manufacturer"]);
        }
    }
}

Conexión a WMI en un equipo remoto