Вызов метода поставщика

Метод поставщика — это метод, реализованный поставщиком инструментария управления Windows (WMI). Метод находится в классе, определенном поставщиком для представления данных из программного или аппаратного обеспечения. Например, класс Win32_Service имеет методы для запуска, остановки, возобновления, приостановки и изменения служб.

Методы поставщика не следует путать со следующими типами методов:

Вызов метода поставщика с помощью скриптов

Любой язык автоматизации, например VBScript, PowerShell или Perl, может вызывать метод WMI. Некоторые языки могут использовать прямой доступ, но другие должны использовать SWbemServices.ExecMethod для косвенного выполнения метода поставщика.

В следующей процедуре описывается вызов метода поставщика с помощью API скриптов и прямого доступа.

Вызов метода поставщика с помощью API скриптов и прямого доступа

  1. Используйте этот подход для VBScript или PowerShell.

  2. Определите, реализован ли метод, который требуется выполнить.

    Некоторые классы имеют определенные методы, которые не поддерживаются поставщиком. Если метод не реализован, его нельзя выполнить. Можно определить, реализован ли метод, проверив, есть ли в методе квалификатор Реализовано . Дополнительные сведения см. в разделах Квалификаторы WMI и Доступ к квалификатору WMI. Можно также определить, имеет ли метод класса поставщика квалификатор Реализован , запустив неподдерживаемую служебную программу Wbemtest.exe, доступную в любой операционной системе с установленным инструментарием WMI.

  3. Определите, является ли метод, который требуется выполнить, статическим или нестатическим методом.

    Статические методы применяются только к классам WMI, но не к конкретным экземплярам класса. Например, метод Create класса Win32_Process является статическим, так как используйте его для создания нового процесса без экземпляра этого класса. Нестатические методы применяются только к экземплярам класса . Например, метод Terminate класса Win32_Process является нестатическим, так как имеет смысл завершать процесс только в том случае, если экземпляр этого процесса существует. Можно определить, является ли метод статическим, проверив, связан ли статический квалификатор с методом .

  4. Получите класс или экземпляр, содержащий метод, который требуется выполнить.

    Дополнительные сведения см. в разделе Получение данных класса или экземпляра WMI.

  5. Настройте все параметры безопасности, которые могут потребоваться методу.

    Часто можно определить привилегии, необходимые для метода, проверив значения в квалификаторе Привилегий метода. Например, метод Shutdown класса Win32_OperatingSystem требует установки привилегии SeShutdownPrivilege. Дополнительные сведения см. в разделе Выполнение привилегированных операций.

  6. Вызовите метод и проверьте возвращаемое значение, чтобы определить, был ли метод успешным.

В следующем примере кода создается процесс Блокнота и он получается с помощью прямого доступа.

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

В следующей процедуре описывается вызов метода поставщика с помощью API скриптов и SWbemServices.ExecMethod.

Вызов метода поставщика с помощью API скриптов и SWbemServices.ExecMethod

  1. Получение определения класса WMI для выполнения статического метода. Получение экземпляра класса WMI для выполнения нестатического метода.
  2. Получите метод для выполнения из коллекции SWbemObject.Methods_ класса или экземпляра с помощью метода SWbemObjectSet.Item .
  3. Получите объект InParameters для метода и настройте параметры, как описано в разделе Конструирование объектов InParameters.
  4. Вызовите метод SWbemServices.ExecMethod для выполнения и назначьте возвращаемое значение объекту SWbemObject для хранения выходных параметров.
  5. Проверьте значения в объекте выходных параметров, чтобы убедиться, что метод выполнен правильно.

В следующем примере кода VBScript выполняется та же операция, что и в предыдущем сценарии, с помощью косвенного подхода путем вызова 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

В следующей процедуре описывается вызов метода поставщика с помощью C++.

Вызов метода поставщика с помощью C++

  1. Подключитесь к WMI.

    Чтобы вызвать метод в WMI, сначала необходимо иметь рабочее подключение к пространству имен WMI. Дополнительные сведения см. в разделах Создание приложения WMI с помощью C++ и Инициализация COM для приложения WMI.

    В следующем примере показано, как подключиться к инструментарию WMI. Дополнительные сведения о проблемах с безопасностью в вызовах поставщика WMI см. в разделе Обслуживание безопасности 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. Вызовите IWbemServices::GetObject , чтобы получить определение класса метода, который требуется вызвать.

    Метод GetObject возвращает указатель IWbemClassObject , указывающий на определение класса.

    hr = pNamespace->GetObject(ClassPath, 0, NULL, &pClass, NULL);
  1. Для методов, требующих входных параметров, вызовите метод IWbemClassObject::GetMethod , чтобы получить объект класса входных параметров.

    GetMethod возвращает указатель IWbemClassObject , указывающий на класс входных параметров.

    hr = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
  1. Создайте экземпляр класса входных параметров с помощью вызова метода IWbemClassObject::SpawnInstance .
    hr = pInClass->SpawnInstance(0, &pInInst);
  1. Задайте свойства класса входных параметров с помощью вызова метода IWbemClassObject::P ut .
    VARIANT var;
    var.vt = VT_BSTR;
    var.bstrVal= SysAllocString(L"hello");
    hr = pInInst->Put(ArgName, 0, &var, 0);
    VariantClear(&var);
  1. Вызовите метод с помощью вызова IWbemServices::ExecMethod или IWbemServices::ExecMethodAsync.

    Для ExecMethod инструментарий WMI возвращает все выходные параметры в вызове . Для ExecMethodAsync WMI возвращает все выходные параметры через вызов IWbemObjectSink. Дополнительные сведения см. в разделе Вызов метода.

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

Следующий код является полным примером вызова метода поставщика.

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

Вызов метода