使用 C++ 删除 WMI 实例
Deleting WMI instance with C++
我发现了一些使用 C# 和 VBS 删除 WMI 实例的示例,但是我需要用 C++ 实现它。
我的示例代码:
CoInitialize(NULL);
HRESULT hRes;
//Obtain the initial locator to WMI
CComPtr<IWbemLocator> pLoc = NULL;
hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*) &pLoc);
if(FAILED(hRes))
return 1;
//Connect to WMI through the IWbemLocator::ConnectServer method
CComPtr<IWbemServices> pSvc = NULL;
//Connect to the root namespace with the current user and obtain pointer pSvc to make IWbemServices calls.
hRes = pLoc->ConnectServer(L"ROOT\SUBSCRIPTION", NULL, NULL, 0, NULL, 0, 0, &pSvc);
if(FAILED(hRes))
return 1;
hRes = pSvc->DeleteInstance(
L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'",
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
return 0;
据此我发现 here and here, my code should work. I surely have CommandLineEventConsumer
named {709782F3-E860-488E-BD8A-89FBC8C1495C}
我的代码在 IWbemServices::DeleteInstance
上失败,错误代码 0x80041008
(调用的参数之一不正确)。
如果有人发现我的代码中有错误,我将不胜感激。或者可能需要一些特权才能做到这一点?
IWbemServices::DeleteInstance 的第一个参数是 BSTR
。 BSTR
与 UTF-16 编码的 C 风格字符串的不同之处在于它存储显式长度参数。即使 BSTR
是 wchar_t*
类型,您也不能传递普通字符串文字来代替 BSTR
.
要从字符串文字创建 BSTR
,您需要调用 SysAllocString:
BSTR objPath = ::SysAllocString(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
objPath,
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
::SysFreeString(objPath);
或者,由于您已经在 CComPtr
使用 ATL,您可以使用 CComBSTR 让您的生活更轻松:
CComBSTR objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
objPath,
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
注意:IWbemLocator::ConnectServer也需要BSTR
s作为参数。文档页面上提供的示例确实传递了一个普通的 C 风格字符串,因此当出现无效参数时,IWbemLocator
接口可能更宽容。
我找到了两个解决方案:
1.Remove WBEM_FLAG_RETURN_IMMEDIATELY
标志。
_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(objPath, 0, NULL, NULL);
2.Pass IWbemCallResult
结果。
_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
CComPtr<IWbemCallResult> pRes = NULL;
hRes = pSvc->DeleteInstance(objPath, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pRes);
没有深入研究,但它是双向的。看起来规格并非 100% 正确。
我发现了一些使用 C# 和 VBS 删除 WMI 实例的示例,但是我需要用 C++ 实现它。
我的示例代码:
CoInitialize(NULL);
HRESULT hRes;
//Obtain the initial locator to WMI
CComPtr<IWbemLocator> pLoc = NULL;
hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*) &pLoc);
if(FAILED(hRes))
return 1;
//Connect to WMI through the IWbemLocator::ConnectServer method
CComPtr<IWbemServices> pSvc = NULL;
//Connect to the root namespace with the current user and obtain pointer pSvc to make IWbemServices calls.
hRes = pLoc->ConnectServer(L"ROOT\SUBSCRIPTION", NULL, NULL, 0, NULL, 0, 0, &pSvc);
if(FAILED(hRes))
return 1;
hRes = pSvc->DeleteInstance(
L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'",
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
return 0;
据此我发现 here and here, my code should work. I surely have CommandLineEventConsumer
named {709782F3-E860-488E-BD8A-89FBC8C1495C}
我的代码在 IWbemServices::DeleteInstance
上失败,错误代码 0x80041008
(调用的参数之一不正确)。
如果有人发现我的代码中有错误,我将不胜感激。或者可能需要一些特权才能做到这一点?
IWbemServices::DeleteInstance 的第一个参数是 BSTR
。 BSTR
与 UTF-16 编码的 C 风格字符串的不同之处在于它存储显式长度参数。即使 BSTR
是 wchar_t*
类型,您也不能传递普通字符串文字来代替 BSTR
.
要从字符串文字创建 BSTR
,您需要调用 SysAllocString:
BSTR objPath = ::SysAllocString(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
objPath,
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
::SysFreeString(objPath);
或者,由于您已经在 CComPtr
使用 ATL,您可以使用 CComBSTR 让您的生活更轻松:
CComBSTR objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
objPath,
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
注意:IWbemLocator::ConnectServer也需要
BSTR
s作为参数。文档页面上提供的示例确实传递了一个普通的 C 风格字符串,因此当出现无效参数时,IWbemLocator
接口可能更宽容。
我找到了两个解决方案:
1.Remove WBEM_FLAG_RETURN_IMMEDIATELY
标志。
_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(objPath, 0, NULL, NULL);
2.Pass IWbemCallResult
结果。
_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
CComPtr<IWbemCallResult> pRes = NULL;
hRes = pSvc->DeleteInstance(objPath, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pRes);
没有深入研究,但它是双向的。看起来规格并非 100% 正确。