Reputation: 8946
I have found some samples with C# and VBS for WMI instance deletion, however I need this implemented with C++.
My sample code:
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;
According to that I've found here and here, my code should work. I surely have CommandLineEventConsumer
named {709782F3-E860-488E-BD8A-89FBC8C1495C}
And my code fails on IWbemServices::DeleteInstance
, error code 0x80041008
(One of the parameters to the call is not correct).
I would appreciate if someone spot mistake in my code. Or maybe some privileges are required to do that?
Upvotes: 2
Views: 1099
Reputation: 8946
I have found two solutions:
1.Remove WBEM_FLAG_RETURN_IMMEDIATELY
flag.
_bstr_t objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(objPath, 0, NULL, NULL);
2.Pass IWbemCallResult
for result.
_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);
Didn't investigate a lot, but it works both ways. Looks like specs aren't 100% correct.
Upvotes: 3
Reputation: 51464
The first parameter to IWbemServices::DeleteInstance is a BSTR
. A BSTR
is different from a UTF-16 encoded C-style string in that it stores an explicit length argument. Even though BSTR
is of type wchar_t*
, you cannot pass a plain string literal in place of a BSTR
.
To create a BSTR
from a string literal you need to call SysAllocString:
BSTR objPath = ::SysAllocString(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
objPath,
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
::SysFreeString(objPath);
Alternatively, since you are already using ATL for CComPtr
you could use CComBSTR to make your life easier:
CComBSTR objPath(L"CommandLineEventConsumer.Name='{709782F3-E860-488E-BD8A-89FBC8C1495C}'");
hRes = pSvc->DeleteInstance(
objPath,
WBEM_FLAG_RETURN_IMMEDIATELY, NULL, NULL);
BSTR
s as parameters. The sample provided on the documentation page does pass a plain C-style string, so maybe the IWbemLocator
interface is more forgiving when presented invalid parameters.
Upvotes: 3