Поделиться через


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Часто можно определить привилегии, необходимые методу, проверив значения в квалификаторе Привилегий метода. Например, метод Win32_OperatingSystem класса Shutdown требует задать привилегию 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::Put.
    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.

    Для ExecMethodWMI возвращает все выходные параметры в вызове. Для ExecMethodAsyncWMI возвращает все выходные параметры с помощью вызова 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;
}

вызов метода