【发布时间】:2015-05-13 17:42:48
【问题描述】:
我正在尝试使用 SoftwareLicensingService::InstallProductKey 通过服务中的 WMI/C++ 在 Windows 7 上安装产品密钥。但是,每次我尝试通过 IWbemServices::ExecMethod 调用该方法时,我都会得到 0x8004102f,即 WBEM_E_INVALID_METHOD_PARAMETERS。我认为这与我传递的产品密钥有关,但此后我为 Win32_WindowsProductActivation::ActivateOnline [这是 XP 上可用的无参数方法] 尝试了类似的代码,但出现相同的错误.有谁知道下面我的代码片段中有什么可疑之处(为了简短起见,我跳过了一些清理代码)?然而,相同的代码序列成功地调用了其他 WMI 方法。
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = S_OK;
IWbemLocator *pLoc = NULL;
IWbemServices *pServices = NULL;
IWbemClassObject *pInputParamsClass = NULL;
IWbemClassObject *pInputParams = NULL;
IWbemClassObject *pOutputParams = NULL;
IWbemClassObject *pLicensingClsObj = NULL;
VARIANT vtProductKey = {0};
VARIANT vtPath = {0};
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if(FAILED(hr))
goto cleanup;
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
_ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
goto cleanup;
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
_ASSERT(SUCCEEDED(hr) && (NULL != pLoc));
if(FAILED(hr) || (NULL == pLoc))
goto cleanup;
hr = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL,
0, 0, &pServices);
_ASSERT(SUCCEEDED(hr) && (NULL != pServices));
if(FAILED(hr) || (NULL == pServices))
goto cleanup;
hr = CoSetProxyBlanket(pServices, RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE);
_ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
goto cleanup;
hr = pServices->GetObject(_bstr_t(L"SoftwareLicensingService"),
0, NULL, &pLicensingClsObj, NULL);
_ASSERT(SUCCEEDED(hr) && (NULL != pLicensingClsObj));
if(FAILED(hr) || (NULL == pLicensingClsObj))
goto cleanup;
hr = pLicensingClsObj->Get(L"__Path", 0, &vtPath, 0, 0);
_ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
goto cleanup;
hr = pLicensingClsObj->GetMethod(L"InstallProductKey", 0,
&pInputParamsClass, NULL);
_ASSERT(SUCCEEDED(hr) && (NULL != pInputParamsClass));
if(FAILED(hr) || (NULL == pInputParamsClass))
goto cleanup;
hr = pInputParamsClass->SpawnInstance(0, &pInputParams);
_ASSERT(SUCCEEDED(hr) && (NULL != pInputParams));
if(FAILED(hr) || (NULL == pInputParams))
goto cleanup;
vtProductKey.vt = VT_BSTR;
vtProductKey.bstrVal = SysAllocString(L"XXXXXXXXXXXXXXXXXXXXXXXXX");
hr = pInputParams->Put(L"ProductKey", 0, &vtProductKey, 0);
_ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
goto cleanup;
hr = pServices->ExecMethod(vtPath.bstrVal,
_bstr_t(L"InstallProductKey"),
0, NULL, pInputParams,
&pOutputParams, NULL);
_ASSERT(SUCCEEDED(hr) && (NULL != pOutputParams));
if(FAILED(hr) || (NULL == pOutputParams))
goto cleanup;
hr = S_OK;//all success
cleanup:
if(NULL != pLoc)
{
pLoc->Release();
pLoc = NULL;
}
if(NULL != pServices)
{
pServices->Release();
pServices = NULL;
}
(VOID)CoUninitialize();
return hr;
}
【问题讨论】:
-
"ROOT\CIMV2"必须是"ROOT\\CIMV2"。您对任何 COM 调用的错误检查在哪里?你如何填充vtProductKey?请提供MCVE。 -
@Remy - 这是一个错字。假设这是带错误检查的工作代码并成功调用其他 wmi 方法。我会修复有问题的字符串。
-
请不要让人假设。请提供“实际”代码,而不是“简化”代码。
-
@Remy 道歉,发布实际代码将违反公司政策。谢谢。
-
因此需要一个能够重现相同问题的 MCVE。但是,除了
vtProductKey的值之外,此代码示例中没有任何内容是专有的。