Partilhar via


Chamando um método de provedor

Um método de provedor é um método que é 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 do provedor não devem ser confundidos com os seguintes tipos de métodos:

Chamando um método de provedor usando scripts

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

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

Para chamar um método de provedor usando a API de script e 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 são suportados por um provedor. Se um método não for implementado, você não poderá executá-lo. Você pode determinar se um método é implementado verificando se o método tem o qualificador Implementado. Para obter mais informações, consulte Qualificadores WMI e Acessar um Qualificador WMI. Você também pode determinar se um método de classe de provedor tem o qualificador Implementado definido utilizando o utilitário Wbemtest.exe sem suporte, disponível em qualquer sistema operativo com 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.

    Os métodos estáticos aplicam-se apenas a classes 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 usá-lo para criar um novo processo sem uma instância dessa classe. Os métodos não estáticos aplicam-se apenas 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 existir 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 instância que contém o método que você deseja executar.

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

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

    Muitas vezes, pode determinar os privilégios que um método requer examinando os valores no qualificador de Privilégios de do método. Por exemplo, a classe Win32_OperatingSystemmétodo Shutdown requer que você defina o privilégio "SeShutdownPrivilege". Para obter mais informações, consulte Executando operações privilegiadas.

  6. Chame o método e examine o valor de retorno 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 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 SWbemServices.ExecMethod

  1. Recupere a definição de classe WMI para executar um método estático. Recupere a instância da classe 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étodoSWbemObjectSet.Item.
  3. Obtenha um objeto InParameters para o método e configure os parâmetros conforme descrito em Constructing InParameters Objects.
  4. Chame o SWbemServices.ExecMethod método para executar e atribuir o valor de retorno a um objeto SWbemObjectpara 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 chamando 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 de trabalho com um namespace WMI. Para obter mais informações, consulte Criando um aplicativo WMI usando C++ e Inicializando COM para um aplicativo WMI.

    O exemplo a seguir mostra como se conectar ao WMI. Para obter mais informações sobre problemas de segurança em chamadas de provedor WMI, consulte Mantendo 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 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 métodos que exigem parâmetros de entrada, chame o IWbemClassObject::GetMethod método para obter o objeto de classe de parâmetro de entrada.

    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 de parâmetro de entrada com uma chamada para o IWbemClassObject::SpawnInstance método.
    hr = pInClass->SpawnInstance(0, &pInInst);
  1. Defina as propriedades da classe de parâmetro de entrada com uma chamada para o 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 ExecMethod, o WMI retorna todos os parâmetros de saída na chamada. Para ExecMethodAsync, o WMI retorna quaisquer parâmetros de saída por meio de uma chamada para IWbemObjectSink. Para obter mais informações, consulte chamando 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;
}

Chamando um método