如何解决调用AddMember()返回“ WBEM_E_INVALID_METHOD_PARAMETERS”的错误?

时间:2019-04-17 02:54:49

标签: c++ wmi hyper-v

我使用下面的powershell脚本为虚拟机提供了rct的快照。

$vm1 = Get-WmiObject -ns root\Virtualization\v2 Msvm_ComputerSystem |?{$_.elementname -eq "backup_test4"}
$cms = Get-WmiObject -ns root\Virtualization\v2 Msvm_CollectionManagementService
$result = $cms.DefineCollection("rcttest", $null, 0)
$coll = [wmi]$result.DefinedCollection
$result = $cms.AddMember($vm1, $coll)
$csss = Get-WmiObject -ns root\Virtualization\v2 Msvm_CollectionSnapshotService                                         
$result = $csss.CreateSnapshot([string]$coll, $null, 32768, $null)

它可以正常生成快照。因此,我将使用C ++进行重构。我的代码段如下:

HRESULT hresult = E_FAIL;
BSTR collectionClass = L"Msvm_CollectionManagementService";
IWbemClassObject* pInClass = NULL;
IWbemClassObject* pOutClass = NULL;
hresult = m_pWbemServices->GetObject(collectionClass,
    0,
    NULL,
    &m_pWbemClassObject,
    NULL);
if (FAILED(hresult)){
    string msg = "Failed to get object.";
    throw std::exception(msg.c_str());
}
// define collection
BSTR methodName1 = L"DefineCollection";
hresult = m_pWbemClassObject->GetMethod(
    methodName1,
    0,
    &pInClass,
    &pOutClass);
if (FAILED(hresult)){
    string msg = "Failed to get method";
    throw std::exception(msg.c_str());
}

根据DefineCollection()enter link description here的用法,您需要为其设置三个三个参数,即集合名称,GUID和类型。代码段如下:

//set param 
VARIANT var;
BSTR paramName1 = L"Name";
var.vt = VT_BSTR;
var.bstrVal = _bstr_t(_collectionName.c_str());

hresult = pInClass->Put(paramName1,
    0,
    &var,
    0);
if (FAILED(hresult)){
    string msg = "Failed to set property.";
    throw std::exception(msg.c_str());
}

BSTR paramName2 = L"Id";
var.vt = VT_BSTR;
var.bstrVal = _bstr_t("");
hresult = pInClass->Put(paramName2,
    0,
    &var,
    0);
if (FAILED(hresult)){
    string msg = "Failed to set property.";
    throw std::exception(msg.c_str());
}

BSTR paramName3 = L"Type";
var.vt = VT_I2;
var.iVal = (uint16_t)0;
if (FAILED(hresult)){
    string msg = "Failed to set property.";
    throw std::exception(msg.c_str());
}

string SqlStr = "SELECT * FROM Msvm_CollectionManagementService";
cout << "sqlstr:" << SqlStr << endl;
IEnumWbemClassObject* pEnumerator = doExecQuery(SqlStr);

IWbemClassObject *pClassObj = NULL;
ULONG uReturn = 0;

    while (1){
        hresult = pEnumerator->Next(
            WBEM_INFINITE,
            1,
            &pClassObj,
            &uReturn);

        if (FAILED(hresult)){
            string msg = "Failed to get computer system.";
            throw std::exception(msg.c_str());
        }
        break;
    }
    if (!pClassObj){
        string msg = "The virtual machine was not found.";
        throw std::exception(msg.c_str());
    }
    pClassObj->Get(L"__Path", 0, &var, 0, 0);

//invoke method
hresult = m_pWbemServices->ExecMethod(
    var.bstrVal,
    methodName1,
    0,
    NULL,
    pInClass,
    &pOutClass,
    NULL);
if (FAILED(hresult)){
    string msg = "Failed to invoke method.";
    throw std::exception(msg.c_str());
}

根据AddMember()enter link description here的用法和脚本,我需要添加两个参数,Member和Collection。我做到了。

VARIANT var;
BSTR paramName4 = L"Member";
//var.vt = VT_BYREF | VT_UNKNOWN;
//var.ppunkVal = (IUnknown**)m_pComputerSystem;
var.vt = VT_BYREF;
var.byref = (PVOID)m_pComputerSystem;
//var.vt = VT_UNKNOWN;
//var.punkVal = (IUnknown*)pInClass;

hresult = pInClass->Put(paramName4,
    0,
    &var,
    0);
if (FAILED(hresult))
{
    string msg = "Failed to set property.";
    throw std::exception(msg.c_str());
}

BSTR paramName5 = L"Collection";
//var.vt = VT_BYREF | VT_UNKNOWN;
//var.ppunkVal = (IUnknown**)&collectionName;
//var.vt = VT_BYREF;
//var.byref = (PVOID)collectionName;
var.vt = VT_UNKNOWN;
var.punkVal = (IUnknown*)collectionName;
hresult = pInClass->Put(paramName5,
    0,
    &var,
    0);
if (FAILED(hresult))
{
    string msg = "Failed to set property.";
    throw std::exception(msg.c_str());
}

string SqlStr = "SELECT * FROM Msvm_CollectionManagementService";
cout << "sqlstr:" << SqlStr << endl;
IEnumWbemClassObject* pEnumerator = doExecQuery(SqlStr);

IWbemClassObject *pClassObj = NULL;
ULONG uReturn = 0;

while (1)
{
    hresult = pEnumerator->Next(
        WBEM_INFINITE,
        1,
        &pClassObj,
        &uReturn);

    if (FAILED(hresult))
    {
        string msg = "Failed to get computer system.";
        throw std::exception(msg.c_str());
    }
    break;
}
if (!pClassObj)
{
    string msg = "The virtual machine was not found.";
    throw std::exception(msg.c_str());
}
pClassObj->Get(L"__Path", 0, &var, 0, 0);

//invoke method
hresult = m_pWbemServices->ExecMethod(
    var.bstrVal,
    methodName2,
    0,
    NULL,
    pInClass,
    &pOutClass,
    NULL);
if (FAILED(hresult))
{
    string msg = "Failed to invoke method.";
    throw std::exception(msg.c_str());
}

每次执行ExecMethod()的返回值为2147749935(0x8004102F)。 根据MSDN对AddMember()参数的描述,我并不真正了解Member和Collection是什么。我通过了这两个参数。这应该是真的错误,但是我找不到。请给我一些指导,谢谢

0 个答案:

没有答案