Enumeração do WMI

Enumeração é o ato de mover-se em um conjunto de objetos e possivelmente modificar cada objeto enquanto se move. Por exemplo, você pode enumerar em um conjunto de objetos Win32_DiskDrive para localizar um número de série específico. Observe que, embora você possa enumerar qualquer objeto, o WMI retorna apenas objetos aos quais você tem acesso de segurança.

Enumerações de grandes conjuntos de dados podem exigir uma grande quantidade de recursos e prejudicar o desempenho. Para obter mais informações, confira Como aprimorar o desempenho da enumeração. Você também pode solicitar dados com uma consulta mais específica. Para obter mais informações, confira Consultar o WMI.

As seguintes seções serão abordadas neste tópico:

Como enumerar o WMI usando o PowerShell

Se você não sabe o caminho do objeto de uma instância específica ou quer recuperar todas as instâncias de uma classe específica, use Get-WmiObject, com o nome da classe no parâmetro -class. Se você quer usar uma consulta, use o parâmetro -query.

O procedimento a seguir descreve como enumerar as instâncias de uma classe usando o PowerShell.

Para enumerar as instâncias de uma classe usando o PowerShell

  1. Enumerar as instâncias com uma chamada ao cmdlet Get-WmiObject.

    O Get-WmiObject retorna uma coleção de um ou mais objetos do WMI, nos quais você pode enumerar. Para obter mais informações, consulte Acessar uma coleção.

    Se você quiser recuperar uma instância de classe do WMI em outro namespace ou em um computador diferente, especifique o computador e o namespace nos parâmetros -computer e -namespace, respectivamente. Para obter mais informações, consulte Como criar um script do WMI. Isso só funcionará se você tiver os privilégios de acesso apropriados. Para obter mais informações, confira Manutenção da segurança do WMI e Executando operações privilegiadas.

  2. Recupere as instâncias individuais desejadas usando os membros da coleção.

O exemplo de código a seguir recupera uma coleção do PowerShell e exibe a propriedade de tamanho de todas as instâncias de unidades lógicas no computador local.

$objCol = get-wmiobject -class "Win32_LogicalDisk"

# Or, alternately
#$objCol = get-wmiobject -Query "SELECT * FROM Win32_LogicalDisk"

foreach ($Drive in $objCol)
{
    if ($Drive.size -ne $null)
    { "Drive " + $Drive.deviceID + " contains " + $Drive.size + " bytes" }
    else
    { "Drive " + $Drive.deviceID + " is not available." }
}

Como enumerar o WMI usando C# (Microsoft.Management.Infrastructure)

  1. Adicione uma referência ao assembly de referência Microsoft.Management.Infrastructure. (Esse assembly é fornecido como parte do SDK (Software Development Kit) do Windows para o Windows 8).
  2. Adicione uma instrução using para o namespace Microsoft.Management.Infrastructure.
    using Microsoft.Management.Infrastructure;
  1. Instancie um objeto CimSession. O snippet a seguir usa o valor padrão "localhost" para o método CimSession.Create.
    CimSession cimSession = CimSession.Create("localhost");
  1. Chame o método CimSession.QueryInstances passando o namespace CIM desejado e o WQL a ser usado. O snippet a seguir retornará duas instâncias que representam dois processos padrão do Windows em que a propriedade de manipulação (que representa uma ID de processo ou PID) tem um valor de 0 ou 4.
    IEnumerable<CimInstance> queryInstances =     
      cimSession.QueryInstances(@"root\cimv2", 
                                "WQL", 
                                @"select name from win32_process where handle = 0 or handle = 4");
  1. Execute um loop nos objetos CimInstance retornados.
    foreach (CimInstance cimInstance in enumeratedInstances)
    { 
      Console.WriteLine("Process name: {0}", cimInstance.CimInstanceProperties["Name"].Value);  
    }

O exemplo de código a seguir enumera todas as instâncias da classe Win32_Process (que representa processos ativos) no computador local e imprime o nome de cada processo.

Observação

Em um aplicativo real, você definiria como parâmetros o nome do computador ("localhost") e o namespace CIM ("root\cimv2"). Por questão de simplicidade, esses parâmetros foram inseridos no código neste exemplo.

 

using System;
using System.Collections.Generic;
using Microsoft.Management.Infrastructure;

public partial class MI
{
    static void PrintCimInstance(CimInstance cimInstance)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine("{0} properties", cimInstance.CimSystemProperties.ClassName);
        Console.ResetColor();

        Console.WriteLine(String.Format("{0,-5}{1,-30}{2,-15}{3,-10}", 
                                        "Key?", "Property", "Type", "Value"));

        foreach (var enumeratedProperty in cimInstance.CimInstanceProperties)
        {
            bool isKey = ((enumeratedProperty.Flags & CimFlags.Key) == CimFlags.Key);

            if (enumeratedProperty.Value != null)
            {
                Console.WriteLine(
                    "{0,-5}{1,-30}{2,-15}{3,-10}",
                    isKey == true ? "Y" : string.Empty,
                    enumeratedProperty.Name,
                    enumeratedProperty.CimType,
                    enumeratedProperty.Value);
            }
        }
        Console.WriteLine();
    }

    public static void QueryInstance(string query)
    {
        try
        {
            CimSession cimSession = CimSession.Create("localhost");

            IEnumerable<CimInstance> queryInstances = 
              cimSession.QueryInstances(@"root\cimv2", "WQL", query);
            foreach (CimInstance cimInstance in queryInstances)
            {
                //Use the current instance. This example prints the instance. 
                PrintCimInstance(cimInstance);
            }
        }
         catch (CimException ex) 
        { 
            // Handle the exception as appropriate.
            // This example prints the message.
            Console.WriteLine(ex.Message); 
        }
    }
}

using System;

namespace MIClientManaged
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.Write(&quot;Enter WQL (x = Quit): &quot;);
                string query = Console.ReadLine().ToUpper();
                if (query.CompareTo(&quot;X&quot;) == 0) break;
                MI.QueryInstance(query);
            }
        }
    }
}

Enumerando o WMI usando C# (System.Management)

Se você não souber o caminho do objeto de uma instância específica ou quiser recuperar todas as instâncias de uma classe específica, use o objeto ManagementClass para recuperar um ManagementObjectCollection que contém todas as instâncias de uma determinada classe no namespace do WMI. Como alternativa, você pode consultar o WMI por meio de um ManagementObjectSearcher para obter o mesmo conjunto de objetos.

Observação

O System.Management era o namespace original do .NET usado para acessar o WMI. No entanto, as APIs nesse namespace geralmente são mais lentas e não escalam tão bem em relação às contrapartes mais modernas do Microsoft.Management.Infrastructure.

 

O procedimento a seguir descreve como enumerar as instâncias de uma classe usando o C#.

Para enumerar as instâncias de uma classe usando o C#

  1. Enumere as instâncias com uma chamada para ManagementClass.GetInstances.

    O método GetInstances retorna uma coleção ou um conjunto de objetos por meio dos quais você pode enumerar. Para obter mais informações, consulte Acessar uma coleção. A coleção retornada é, na verdade, um objeto ManagementObjectCollection, portanto, qualquer um dos métodos desse objeto pode ser chamado.

    Se você quiser recuperar uma instância de classe do WMI em outro namespace ou em um computador diferente, especifique o computador e o namespace no parâmetro path. Para obter mais informações, consulte Como criar um script do WMI. Isso só funcionará se você tiver os privilégios de acesso apropriados. Para obter mais informações, confira Manutenção da segurança do WMI e Executando operações privilegiadas.

  2. Recupere as instâncias individuais desejadas usando os membros da coleção.

O exemplo de código a seguir recupera uma coleção do C# e exibe a propriedade de tamanho de todas as instâncias de unidades lógicas no computador local.

using System.Management;
...

ManagementClass mc = new ManagementClass("Win32_LogicalDisk");
ManagementObjectCollection objCol = mc.GetInstances();

//or, alternately
//ManagementObjectSearcher mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");
//ManagementObjectCollection objCol = mgmtObjSearcher.Get();

if (objCol.Count != 0)
{
   foreach (ManagementObject Drive in objCol)
   {
      if (Drive["size"] != null)
      {
         Console.WriteLine("Drive {0} contains {1} bytes.", Drive["deviceID"], Drive["size"]);
      }
      else
      {
         Console.WriteLine("Drive {0} is not available.", Drive["deviceID"]);
      }
   }
}
Console.ReadLine();

Como enumerar o WMI usando VBScript

Se você não souber o caminho do objeto de uma instância específica ou quiser recuperar todas as instâncias de uma classe específica, use o método SWbemServices.InstancesOf para retornar uma enumeração SWbemObjectSet de todas as instâncias de uma classe. Você também pode consultar o WMI por meio de SWbemServices.ExecQuery para obter o mesmo conjunto de objetos.

O procedimento a seguir descreve como enumerar as instâncias de uma classe usando a VBScript.

Para enumerar as instâncias de uma classe usando a VBScript

  1. Enumere as instâncias com uma chamada ao método SWbemServices.InstancesOf.

    O método InstancesOf retorna uma coleção ou um conjunto de objetos por meio dos quais você pode enumerar. Para obter mais informações, consulte Acessar uma coleção. A coleção retornada é, na verdade, um objeto SWbemObjectSet, portanto, qualquer um dos métodos desse objeto pode ser chamado.

    Se você quiser recuperar uma instância de classe do WMI em outro namespace ou em um computador diferente, especifique o computador e o namespace no moniker. Para obter mais informações, consulte Como criar um script do WMI. Isso só funcionará se você tiver os privilégios de acesso apropriados. Para obter mais informações, confira Manutenção da segurança do WMI e Executando operações privilegiadas.

  2. Recupere as instâncias individuais desejadas usando os métodos da coleção.

O exemplo de código a seguir recupera um objeto SWbemServices e, em seguida, executa o método InstancesOf para exibir a propriedade de tamanho de todas as instâncias de unidades lógicas no computador local.

Set objCol = GetObject("WinMgmts:").InstancesOf("Win32_LogicalDisk")
For Each Drive In objCol
    If Not IsNull(Drive.Size) Then    
       WScript.Echo ("Drive " & Drive.deviceid & " contains " & Drive.Size & " bytes")
    Else
       WScript.Echo ("Drive " & Drive.deviceid & " is not available.")
    End If
Next

Como enumerar o WMI usando C++

Além de executar a enumeração básica, você pode definir vários sinalizadores e propriedades para aumentar o desempenho da enumeração. Para obter mais informações, confira Como aprimorar o desempenho da enumeração.

Para enumerar um conjunto de objetos no WMI

  1. Crie uma interface IEnumWbemClassObject que descreve o conjunto de objetos que você deseja enumerar.

    Um objeto IEnumWbemClassObject contém uma lista que descreve um conjunto de objetos do WMI. Você pode usar os métodos IEnumWbemClassObject para enumerar encaminhamentos, ignorar objetos, começar no início e copiar o enumerador. A tabela a seguir lista os métodos usados para criar enumeradores para diferentes tipos de objetos do WMI.

    Objeto Método
    Classe
    IWbemServices::CreateClassEnum
    [IWbemServices::CreateClassEnumAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createclassenumasync)
    Instância
    IWbemServices::CreateInstanceEnum
    [IWbemServices::CreateInstanceEnumAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createinstanceenumasync)
    Resultado da consulta
    IWbemServices::ExecQuery
    [IWbemServices::ExecQueryAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execqueryasync)
    Notificação de eventos
    IWbemServices::ExecNotificationQuery
    [IWbemServices::ExecNotificationQueryAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execnotificationqueryasync)

     

  2. Percorra a enumeração retornada usando várias chamadas para IEnumWbemClassObject::Next ou IEnumWbemClassObject::NextAsync.

Para obter mais informações, confira Manipular informações de classe e instância.