Llamada a un método de proveedor

Un método de proveedor es un método implementado por un proveedor de Instrumental de administración de Windows (WMI). El método se encuentra en una clase definida por un proveedor para representar datos de software o hardware. Por ejemplo, la clase Win32_Service tiene métodos para iniciar, detener, reanudar, pausar y cambiar servicios.

Los métodos de proveedor no se deben confundir con los siguientes tipos de métodos:

Llamada a un método de proveedor mediante scripting

Cualquier lenguaje de automatización, como VBScript, PowerShell o Perl, puede llamar a un método de WMI. Algunos lenguajes pueden usar el acceso directo, pero otros deben usar SWbemServices.ExecMethod para ejecutar el método de proveedor indirectamente.

En el procedimiento siguiente se describe cómo llamar a un método de proveedor mediante la API de scripting y el acceso directo.

Para llamar a un método de proveedor mediante la API de scripting y el acceso directo

  1. Use este enfoque para VBScript o PowerShell.

  2. Determine si se implementa el método que quiere ejecutar.

    Algunas clases tienen métodos definidos que no son compatibles con un proveedor. Si no se implementa un método, no se puede ejecutar. Para determinar si se implementa un método, compruebe si tiene el calificador Implemented. Para más información, vea Calificadores de WMI y Acceso a un calificador de WMI. También puede determinar si un método de clase de proveedor tiene establecido el calificador Implemented si ejecuta la utilidad Wbemtest.exe no admitida, disponible en cualquier sistema operativo con WMI instalado.

  3. Determine si el método que quiere ejecutar es un método estático o un método no estático.

    Los métodos estáticos solo se aplican a las clases WMI y no a instancias específicas de una clase. Por ejemplo, el método Create de la clase Win32_Process es un método estático porque se usa para crear un proceso sin una instancia de esta clase. Los métodos no estáticos solo se aplican a instancias de una clase. Por ejemplo, el método Terminate de la clase Win32_Process es un método no estático porque solo tiene sentido finalizar un proceso si existe una instancia de ese proceso. Para determinar si un método es estático, compruebe si el calificador Static está asociado al método.

  4. Recupere la clase o instancia que contiene el método que quiera ejecutar.

    Para más información, vea Recuperación de datos de instancia o clase de WMI.

  5. Configure cualquier valor de seguridad que el método pueda necesitar.

    A menudo puede determinar los privilegios que necesita un método si examina los valores del calificador Privileges del método. Por ejemplo, para el método Shutdown de la clase Win32_OperatingSystem es necesario establecer el privilegio "SeShutdownPrivilege". Para más información, vea Ejecución de operaciones con privilegios.

  6. Llame al método y examine el valor devuelto para determinar si el método se ha ejecutado correctamente.

En el ejemplo de código siguiente se crea un proceso del Bloc de notas y se obtiene el id. de proceso mediante el acceso directo.

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

En el procedimiento siguiente se describe cómo llamar a un método de proveedor mediante la API de scripting y SWbemServices.ExecMethod.

Para llamar a un método de proveedor mediante la API de scripting y SWbemServices.ExecMethod

  1. Recupere la definición de clase WMI para ejecutar un método estático. Recupere la instancia de la clase WMI para ejecutar un método no estático.
  2. Recupere el método que se va a ejecutar desde la colección SWbemObject.Methods_ de la clase o instancia con el método SWbemObjectSet.Item.
  3. Obtenga un objeto InParameters para el método y configure los parámetros como se describe en Construcción de objetos InParameters.
  4. Llame al método SWbemServices.ExecMethod para ejecutarlo y asigne el valor devuelto a un objeto SWbemObject para almacenar los parámetros de salida.
  5. Compruebe los valores del objeto de parámetros de salida para comprobar que el método se ha ejecutado correctamente.

El siguiente ejemplo de código VBScript realiza la misma operación que el script anterior mediante el enfoque indirecto con una llamada a 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

En el procedimiento siguiente se describe cómo llamar a un método de proveedor mediante C++.

Para llamar a un método de proveedor mediante C++

  1. Conéctese a WMI.

    Para llamar a un método en WMI, primero debe tener una conexión funcional a un espacio de nombres WMI. Para más información, vea Creación de una aplicación de WMI con C++ e Inicialización de COM para una aplicación de WMI.

    En el ejemplo siguiente se muestra cómo conectarse a WMI. Para más información sobre los problemas de seguridad en las llamadas de proveedor de WMI, vea Mantenimiento de la seguridad de 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. Llame a IWbemServices::GetObject para recuperar la definición de la clase del método que quiera llamar.

    El método GetObject devuelve un puntero IWbemClassObject que apunta a la definición de clase.

    hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);
  1. Para los métodos que necesitan parámetros de entrada, llame al método IWbemClassObject::GetMethod para obtener el objeto de clase de parámetro de entrada.

    GetMethod devuelve un puntero IWbemClassObject que apunta a la clase de parámetro de entrada.

    hr = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
  1. Genere una instancia de la clase de parámetro de entrada con una llamada al método IWbemClassObject::SpawnInstance.
    hr = pInClass->SpawnInstance(0, &pInInst);
  1. Establezca las propiedades de la clase de parámetro de entrada con una llamada al 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 el método con una llamada a IWbemServices::ExecMethod o IWbemServices::ExecMethodAsync.

    Para ExecMethod, WMI devuelve los parámetros de salida de la llamada. Para ExecMethodAsync, WMI devuelve los parámetros de salida mediante una llamada a IWbemObjectSink. Para más información, vea Llamada a un método.

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

El código siguiente es un ejemplo completo para llamar a un método de proveedor.

#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;
}

Llamada a un método