プロバイダー メソッドの呼び出し

プロバイダー メソッドは、Windows Management Instrumentation (WMI) プロバイダーによって実装されるメソッドです。 メソッドは、ソフトウェアまたはハードウェアからのデータを表すためにプロバイダーによって定義されたクラスにあります。 たとえば、Win32_Service クラスには、サービスの開始、停止、再開、一時停止、変更を行うメソッドがあります。

プロバイダー メソッドを、次の種類のメソッドと混同しないようにしてください。

スクリプトを使用したプロバイダー メソッドの呼び出し

VBScript、PowerShell、Perl などの任意のオートメーション言語で WMI メソッドを呼び出すことができます。 直接アクセスを使用できる言語もありますが、他の言語ではプロバイダー メソッドを間接的に実行するために SWbemServices.ExecMethod を使用する必要があります。

以下の手順では、Scripting API と直接アクセスを使用してプロバイダー メソッドを呼び出す方法について説明します。

Scripting API と直接アクセスを使用してプロバイダー メソッドを呼び出す場合

  1. VBScript または PowerShell には、この方法を使用します。

  2. 実行するメソッドが実装されているかどうかを確認します。

    一部のクラスには、プロバイダーでサポートされていないメソッドが定義されています。 メソッドが実装されていない場合は、実行できません。 メソッドが実装されているかどうかを確認するには、メソッドに Implemented 修飾子があるかどうかを確認します。 詳細については、「WMI 修飾子」および「WMI 修飾子へのアクセス」を参照してください。 また、プロバイダー クラス メソッドに Implemented 修飾子が設定されているかどうかを確認するために、WMI がインストールされているオペレーティング システムで使用できる、サポートされていないWbemtest.exe ユーティリティを実行することもできます。

  3. 実行するメソッドが"静的メソッド" か非静的メソッドかを確認します。

    静的メソッドは WMI クラスにのみ適用され、クラスの特定のインスタンスには適用されません。 たとえば、Win32_Process クラスの Create メソッドは静的メソッドです。これは、このクラスのインスタンスなしで新しいプロセスを作成するために使用するためです。 非静的メソッドは、クラスのインスタンスにのみ適用されます。 たとえば、Win32_Process クラスの Terminate メソッドは、非静的メソッドです。なぜなら、プロセスのインスタンスが存在する場合にのみプロセスを終了することに意味があるためです。 Static 修飾子がメソッドに関連付けられているかどうかを確認することで、メソッドが静的かどうかを判断できます。

  4. 実行するメソッドを含むクラスまたはインスタンスを取得します。

    詳細については、「WMI クラスまたはインスタンス データの取得」を参照してください。

  5. メソッドで必要になる可能性があるセキュリティ設定を設定します。

    多くの場合、メソッドの Privileges 修飾子の値を調べることで、メソッドに必要な特権を確認できます。 たとえば、Win32_OperatingSystem クラスの Shutdown メソッドでは、"SeShutdownPrivilege" 特権を設定する必要があります。 詳細については、「特権操作の実行」を参照してください。

  6. メソッドを呼び出し、戻り値を調べて、メソッドが成功したかどうかを判断します。

次のコード例では、メモ帳プロセスを作成し、直接アクセスを使用してプロセス ID を取得します。

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

以下の手順では、Scripting API と SWbemServices.ExecMethod を使用してプロバイダー メソッドを呼び出す方法について説明します。

Scripting API と SWbemServices.ExecMethod を使用してプロバイダー メソッドを呼び出すには

  1. 静的メソッドを実行するには WMI クラス定義を取得します。 非静的メソッドを実行するには WMI クラス インスタンスを取得します。
  2. SWbemObjectSet.Item メソッドを使用して、クラスまたはインスタンスの SWbemObject.Methods_ コレクションから実行するメソッドを取得します。
  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 名前空間への接続が動作している必要があります。 詳細については、「C++ を使用した WMI アプリケーションの作成」および「WMI アプリケーションの COM の初期化」を参照してください。

    次の例は、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 の呼び出しでメソッドを呼び出します。

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

メソッドの呼び出し