Condividi tramite


Connessione a WMI in remoto con C#

Come per altri linguaggi, ad esempio PowerShell, VBScript o C++, è possibile usare C# per monitorare in remoto l'hardware e il software nei computer remoti. Le connessioni remote per il codice gestito vengono eseguite tramite lo spazio dei nomi Microsoft.Management. Infrastructure. Le versioni precedenti di WMI usavano lo spazio dei nomi System.Management, incluso qui per completezza.

Nota

System.Management era lo spazio dei nomi .NET originale usato per accedere a WMI; tuttavia, le API in questo spazio dei nomi sono in genere più lente e non si ridimensionano altrettanto bene rispetto alle controparti più moderne Microsoft.Management.Infrastructure.

 

La connessione remota tramite classi nello spazio dei nomi Microsoft.Management.Infrastructure usa DCOM come meccanismo remoto sottostante. Le connessioni remote WMI devono essere conformi ai requisiti di sicurezza DCOM per l'impersonificazione e l'autenticazione. Per impostazione predefinita, un ambito è associato al computer locale e allo spazio dei nomi di sistema "Root\CIMv2". Tuttavia, è possibile modificare sia il computer, il dominio che lo spazio dei nomi WMI a cui si accede. È anche possibile impostare autorità, rappresentazione, credenziali e altre opzioni di connessione.

Per connettersi a WMI in remoto con C# (Microsoft.Management.Infrastructure)

  1. Creare una sessione nel computer remoto con una chiamata a CimSession.Create.

    Se ci si connette a un computer remoto usando le stesse credenziali (dominio e nome utente) con cui si è connessi, è possibile specificare il nome del computer nella chiamata Crea. Una volta ottenuto l'oggetto CimSession, puoi eseguire la query 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);
    

    Per altre informazioni sull'esecuzione di query WMI con l'API Microsoft.Management.Infrastructure in C#, vedere Recupero di dati di istanza o classe WMI.

  2. Se si desidera impostare opzioni diverse per la connessione, ad esempio credenziali, impostazioni locali o livelli di rappresentazione diversi, è necessario usare un oggetto CimSessionOptions nella chiamata a CimSession.Create.

    CimSessionOptions è una classe di base per WSManSessionOptions e DComSessionOptions. È possibile usare entrambi per impostare le opzioni rispettivamente nelle sessioni WS-Man e DCOM. Nell'esempio di codice seguente viene descritto l'uso di un oggetto DComSessionOptions per impostare il livello di rappresentazione su Impersonate.

    string computer = "Computer_B"
    DComSessionOptions DComOptions = new DComSessionOptions();
    DComOptions.Impersonation = ImpersonationType.Impersonate;
    
    CimSession Session = CimSession.Create(computer, DComOptions);
    
  3. Se si desidera impostare le credenziali per la connessione, è necessario creare e aggiungere un oggetto CimCredentials a CimSessionOptions.

    Nell'esempio di codice seguente viene descritta la creazione di una classe WSManSessionOptions, riempindola con il CimSessionOptions appropriato e usandolo in una chiamata 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);
    

    È in genere consigliabile non codificare direttamente una password nelle applicazioni; come indicato nell'esempio di codice precedente, quando possibile cercare di chiedere all'utente la password e memorizzarla in modo sicuro.

WMI è progettato per monitorare l'hardware e il software nei computer remoti. Le connessioni remote per WMI v1 vengono eseguite tramite l'oggetto ManagementScope.

Per connettersi a WMI in remoto con C# (System.Management)

  1. Creare un oggetto ManagementScope usando il nome del computer e il percorso WMI e connettersi alla destinazione con una chiamata a ManagementScope.Connect().

    Se ci si connette a un computer remoto usando le stesse credenziali (dominio e nome utente) con cui si è connessi, è necessario specificare solo il percorso WMI. Dopo aver stabilito la connessione, è possibile eseguire la query 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);
    

    Per altre informazioni sull'esecuzione di query WMI con l'API System.Management in C#, vedere Recupero di una classe WMI o di dati dell'istanza.

  2. Se ci si connette a un computer remoto in un dominio diverso o si usa un nome utente e una password diversi, è necessario utilizzare un oggetto ConnectionOptions nella chiamata al ManagementScope.

    Il ConnectionOptions contiene proprietà per descrivere l'autenticazione, la rappresentazione, il nome utente, la password e altre opzioni di connessione. Nell'esempio di codice seguente viene descritto l'uso di un ConnectionOptions per impostare il livello di impersonazione su Impersonate.

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

    In generale, è consigliabile impostare il livello di impersonazione su Impersonate, a meno che non sia esplicitamente necessario diversamente. Provare inoltre a evitare di scrivere il nome e la password nel codice C#. Se possibile, verificare se è possibile eseguire una query sull'utente per specificarle in modo dinamico in fase di esecuzione.

    Per altri esempi di impostazione di proprietà diverse in una connessione WMI remota, vedere la sezione Esempi della pagina di riferimento ConnectionOptions.

Esempio di Microsoft.Management.Infrastructure

L'esempio di codice C# seguente, basato sul post di blog di seguente in TechNet, descrive come usare CimCredentials e WSManSessionOptions per impostare le credenziali in una connessione 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();
         }
     }
 }

Esempio di System.Management

L'esempio di codice C# seguente descrive una connessione remota generale, usando gli oggetti 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"]);
        }
    }
}

Connessione a WMI su un computer remoto