Chamar um método de provedor

Um método de provedor é um método implementado por um provedor WMI (Instrumentação de Gerenciamento do Windows). O método é encontrado em uma classe definida por um provedor para representar dados de software ou hardware. Por exemplo, a classe Win32_Service tem métodos para iniciar, parar, retomar, pausar e alterar serviços.

Os métodos de provedor não devem ser confundidos com os seguintes tipos de métodos:

Chamar um método de provedor usando scripts

Qualquer linguagem de automação, como VBScript, PowerShell ou Perl, pode chamar um método do WMI. Algumas linguagens podem usar acesso direto, mas outras devem usar o SWbemServices.ExecMethod para executar o método do provedor indiretamente.

O procedimento a seguir descreve como chamar um método de provedor usando a API de Script e o acesso direto.

Para chamar um método de provedor usando a API de Script e o acesso direto

  1. Use essa abordagem para VBScript ou PowerShell.

  2. Determine se o método que você deseja executar está implementado.

    Algumas classes têm métodos definidos que não têm suporte de um provedor. Se um método não estiver implementado, você não poderá executá-lo. Você pode determinar se um método está implementado verificando se o método tem o qualificador Implemented. Para obter mais informações, confira Qualificadores di WMI e Acessar um qualificador do WMI. Você também pode determinar se um método de classe do provedor tem o qualificador Implemented definido executando o utilitário Wbemtest.exe sem suporte, disponível em qualquer sistema operacional com o WMI instalado.

  3. Determine se o método que você deseja executar é um método estático ou um método não estático.

    Métodos estáticos se aplicam somente a classes do WMI e não a instâncias específicas de uma classe. Por exemplo, o método Create da classe Win32_Process é um método estático porque o usa para criar outro processo sem uma instância dessa classe. Métodos não estáticos se aplicam somente a instâncias de uma classe. Por exemplo, o método Terminate da classe Win32_Process é um método não estático porque só faz sentido encerrar um processo se houver uma instância desse processo. Você pode determinar se um método é estático verificando se o qualificador Static está associado ao método.

  4. Recupere a classe ou a instância que contém o método que você deseja executar.

    Para obter mais informações, consulte Recuperar dados de classe ou de instância do WMI.

  5. Defina as configurações de segurança que o método possa exigir.

    Geralmente, você pode determinar os privilégios exigidos por um método examinando os valores no qualificador Privileges do método. Por exemplo, o método Shutdown da classe Win32_OperatingSystem exige que você defina o privilégio "SeShutdownPrivilege". Para obter mais informações, confira Executar operações privilegiadas.

  6. Chame o método e examine o valor retornado para determinar se o método foi bem-sucedido.

O exemplo de código a seguir cria um processo do Bloco de notas e obtém a ID do processo usando o acesso direto.

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer _
    & "\root\cimv2:Win32_Process")

Error = objWMIService.Create("notepad.exe", null, _
    null, intProcessID)
If Error = 0 Then
    Wscript.Echo "Notepad was started with a process ID of " _
       & intProcessID & "."
Else
    Wscript.Echo "Notepad could not be started due to error " _
       & Error & "."
End If  

try
{ 
    $myProcess = ([wmiclass]"win32_process").create("notepad.exe", $null, $null) 
}
catch 
{
    "Notepad could not be started due to the following error:" 
    $error[0]
    return 
}
#else
"Notepad was started with a process ID of " + $myProcess.ProcessID

O procedimento a seguir descreve como chamar um método de provedor usando a API de Script e o SWbemServices.ExecMethod.

Para chamar um método de provedor usando a API de Script e o SWbemServices.ExecMethod

  1. Recupere a definição de classe do WMI para executar um método estático. Recupere a instância da classe do WMI para executar um método não estático.
  2. Recupere o método a ser executado da coleção SWbemObject.Methods_ de sua classe ou instância usando o método SWbemObjectSet.Item.
  3. Obtenha um objeto InParameters para o método e configure os parâmetros conforme descrito em Construir objetos InParameters.
  4. Chame o método SWbemServices.ExecMethod para executar e atribuir o valor retornado a um objeto SWbemObject para armazenar os parâmetros de saída.
  5. Verifique os valores no objeto de parâmetros de saída para verificar se o método foi executado corretamente.

O exemplo de código VBScript a seguir executa a mesma operação que o script anterior pela abordagem indireta por meio da chamada ao de SWBemServices.ExecMethod.

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer _
    & "\root\cimv2")

Set objProcess = objWMIService.Get("Win32_Process")

' Obtain an InParameters object specific to 
'   the Win32_Process.Create method.
Set objInParam = _
    objProcess.Methods_("Create").inParameters.SpawnInstance_()

' Add the input parameters. 
objInParam.Properties_.item("CommandLine") = "Notepad"
objInParam.Properties_.item("CurrentDirectory") = NULL
objInParam.Properties_.item("ProcessStartupInformation") = NULL


Set objOutParams = objProcess.ExecMethod_("Create", objInParam) 
If Error = 0 Then
    Wscript.Echo "Notepad was started with a process ID of " _
       & objOutParams.ProcessId 
Else
    Wscript.Echo "Notepad could not be started due to error " & _
       objOutParams.ReturnValue
End If

O procedimento a seguir descreve como chamar um método de provedor usando C++.

Para chamar um método de provedor usando C++

  1. Conecte-se ao WMI.

    Para chamar um método no WMI, primeiro você deve ter uma conexão funcional com um namespace do WMI. Para obter mais informações, confira Criar um aplicativo do WMI usando C++ e Inicializar o COM para um aplicativo do WMI.

    O exemplo a seguir mostra como se conectar ao WMI. Para obter mais informações sobre problemas de segurança em chamadas ao provedor WMI, consulte Manter a segurança do WMI.

    HRESULT hr = CoInitialize(0);
        hr  =  CoInitializeSecurity(
                NULL, 
                -1, 
                NULL, 
                NULL,
                RPC_C_AUTHN_LEVEL_DEFAULT, 
                RPC_C_IMP_LEVEL_IMPERSONATE, 
                NULL, 
                EOAC_NONE, 
                NULL); 
        hr = CoCreateInstance(CLSID_WbemLocator, 0, 
                CLSCTX_INPROC_SERVER,
                IID_IWbemLocator, (LPVOID *) &pLocator);
        hr = pLocator->ConnectServer(path, NULL, NULL, 
                NULL, 0, NULL, NULL, &pNamespace);
  1. Chame o IWbemServices::GetObject para recuperar a definição da classe do método que você deseja chamar.

    O método GetObject retorna um ponteiro IWbemClassObject que aponta para a definição de classe.

    hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);
  1. Para os métodos que exigem parâmetros de entrada, chame o método IWbemClassObject::GetMethod para obter o objeto de classe do parâmetro de entrada.

    O GetMethod retorna um ponteiro IWbemClassObject que aponta para a classe de parâmetro de entrada.

    hr = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
  1. Gere uma instância da classe do parâmetro de entrada com uma chamada ao método IWbemClassObject::SpawnInstance.
    hr = pInClass->SpawnInstance(0, &pInInst);
  1. Defina as propriedades da classe do parâmetro de entrada com uma chamada ao método IWbemClassObject::Put.
    VARIANT var;
    var.vt = VT_BSTR;
    var.bstrVal= SysAllocString(L"hello");
    hr = pInInst->Put(ArgName, 0, &var, 0);
    VariantClear(&var);
  1. Invoque o método com uma chamada para IWbemServices::ExecMethod ou IWbemServices::ExecMethodAsync.

    Para o ExecMethod, o WMI retorna os parâmetros de saída na chamada. Para o ExecMethodAsync, o WMI retorna todos os parâmetros de saída por meio de uma chamada ao IWbemObjectSink. Para obter mais informações, consulte Chamar um método.

    hr = pNamespace->ExecMethod(ClassPath, MethodName, 0, NULL, pInInst, &pOutInst, NULL);

O código a seguir é um exemplo completo para chamar um método de provedor.

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

int main(int iArgCnt, char ** argv)
{
    IWbemLocator *pLocator = NULL;
    IWbemServices *pNamespace = 0;
    IWbemClassObject * pClass = NULL;
    IWbemClassObject * pOutInst = NULL;
    IWbemClassObject * pInClass = NULL;
    IWbemClassObject * pInInst = NULL;
  
    BSTR path = SysAllocString(L"root\\default");
    BSTR ClassPath = SysAllocString(L"TestMeth");
    BSTR MethodName = SysAllocString(L"Echo");
    BSTR ArgName = SysAllocString(L"sInArg");
    BSTR Text;

    // Initialize COM and connect to WMI.

    HRESULT hr = CoInitialize(0);
    hr  =  CoInitializeSecurity(NULL, -1, NULL, NULL,RPC_C_AUTHN_LEVEL_DEFAULT, 
                                RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); 
    hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
                          IID_IWbemLocator, (LPVOID *) &pLocator);
    hr = pLocator->ConnectServer(path, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);

    // Get the class object for the method definition.

    hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);

    // Get the input-argument class object and 
    // create an instance.

    hr = pClass->GetMethod(MethodName, 0, &pInClass, NULL); 
    hr = pInClass->SpawnInstance(0, &pInInst);

    // Set the property.

    VARIANT var;
    var.vt = VT_BSTR;
    var.bstrVal= SysAllocString(L"hello");
    hr = pInInst->Put(ArgName, 0, &var, 0);
    VariantClear(&var);

    // Call the method.

    hr = pNamespace->ExecMethod(ClassPath, MethodName, 0, NULL, pInInst, &pOutInst, NULL);
    
    // Display the results. Note that the return 
    // value is in the property "ReturnValue"
    // and the returned string is in the 
    // property "sOutArg".

    hr = pOutInst->GetObjectText(0, &Text);
    printf("\nThe object text is:\n%S", Text);

    // Free up resources.

    SysFreeString(path);
    SysFreeString(ClassPath);
    SysFreeString(MethodName);
    SysFreeString(ArgName);
    SysFreeString(Text);
    pClass->Release();
    pInInst->Release();
    pInClass->Release();
    pOutInst->Release();
    pLocator->Release();
    pNamespace->Release();
    CoUninitialize();
    printf("Terminating normally\n");
    return 0;
}

Chamar um método