Partilhar via


Enumerando WMI

Enumeração é o ato de percorrer um conjunto de elementos e, possivelmente, modificar cada um deles no processo. Por exemplo, você pode enumerar através de 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 só retorna objetos aos quais você tem acesso de segurança.

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

As seguintes seções são discutidas neste tópico:

Enumerando WMI usando o PowerShell

Se você não souber o caminho do objeto para uma instância específica ou quiser recuperar todas as instâncias de uma classe específica, use Get-WmiObject, com o nome da classe no parâmetro -class. Se quiser usar uma consulta, você pode usar 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. Enumere as instâncias com uma chamada para o cmdlet Get-WmiObject.

    Get-WmiObject retorna uma coleção de um ou mais objetos WMI, através dos quais você pode enumerar. Para obter mais informações, consulte acessando uma coleção.

    Se desejar recuperar uma instância de classe 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 Criando um script WMI. Isso só funciona se você tiver os privilégios de acesso apropriados. Para obter mais informações, consulte Manutenção da segurança WMI e Execução de operações privilegiadas.

  2. Recupere quaisquer instâncias individuais que desejar 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 para todas as instâncias de discos lógicos 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." }
}

Enumeração do WMI usando C# (Microsoft.Management.Infrastructure)

  1. Adicione uma referência ao assembly de referência Microsoft.Management.Infrastructure. (Esta montagem é fornecida como parte do Windows Software Development Kit (SDK) para Windows 8.)
  2. Adicione uma instrução usando para o namespace Microsoft.Management.Infrastructure.
    using Microsoft.Management.Infrastructure;
  1. Crie um objeto CimSession . O trecho a seguir usa o valor padrão "localhost" para o CimSession.Create método.
    CimSession cimSession = CimSession.Create("localhost");
  1. Chame o método CimSession.QueryInstances passando o namespace CIM desejado e o WQL a ser utilizado. O trecho a seguir retornará duas instâncias que representam dois processos padrão do Windows em que a propriedade handle (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. Percorra os objetos de 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) na máquina 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"). Para fins de simplicidade, eles foram codificados 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("Enter WQL (x = Quit): ");
                string query = Console.ReadLine().ToUpper();
                if (query.CompareTo("X") == 0) break;
                MI.QueryInstance(query);
            }
        }
    }
}

Enumerando WMI usando C# (System.Management)

Se você não souber o caminho do objeto para 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 WMI. Como alternativa, pode consultar o WMI através de um ManagementObjectSearcher para obter o mesmo conjunto de objetos.

Observação

System.Management era o namespace .NET original usado para acessar o WMI; no entanto, as APIs neste namespace geralmente são mais lentas e não são dimensionadas tão bem em relação às suas contrapartes mais modernas Microsoft.Management.Infrastructure.

 

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

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

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

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

    Se desejar recuperar uma instância de classe WMI em outro espaço de nomes ou num computador diferente, especifique o computador e o espaço de nomes no parâmetro de caminho . Para obter mais informações, consulte Criando um script WMI. Isso só funciona se você tiver os privilégios de acesso apropriados. Para obter mais informações, consulte Manter a Segurança WMI e Executar Operações Privilegiadas.

  2. Recupere quaisquer instâncias individuais que desejar usando os membros da coleção.

O exemplo de código a seguir recupera uma coleção C# e, em seguida, exibe a propriedade size para 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();

A Enumeração do WMI usando o VBScript

Se você não souber o caminho do objeto para uma instância específica ou quiser recuperar todas as instâncias de uma classe específica, use o método SWbemServices.InstancesOfpara retornar uma enumeração SWbemObjectSetde todas as instâncias de uma classe. Como alternativa, você pode consultar o WMI através SWbemServices.ExecQuery para obter o mesmo conjunto de objetos.

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

Para enumerar as instâncias de uma classe usando VBScript

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

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

    Se desejar recuperar uma instância de classe WMI em outro namespace ou em um computador diferente, especifique o computador e o namespace no moniker. Para obter mais informações, consulte Criando um script WMI. Isso só funciona se você tiver os privilégios de acesso apropriados. Para mais informações, consulte Manutenção da Segurança WMI e Execução de Operações Privilegiadas.

  2. Recupere quaisquer instâncias individuais que desejar usando os métodos de coleções.

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 para 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

Enumerando 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, consulte melhorando o desempenho da enumeração.

Para enumerar um objeto definido no WMI

  1. Crie um IEnumWbemClassObject interface descrevendo o conjunto de objetos que você deseja enumerar.

    Um IEnumWbemClassObject objeto contém uma lista que descreve um conjunto de objetos WMI. Você pode usar os métodos IEnumWbemClassObject para enumerar para a frente, ignorar objetos, começar a partir do início e copiar o enumerador. A tabela a seguir lista os métodos usados para criar enumeradores para diferentes tipos de objetos 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, consulte Manipulando informações de classe e instância.