2016-05-12 2 views
1

Я нашел несколько примеров с C# и VBS для удаления экземпляра WMI, однако мне это нужно реализовать с C++.Удаление экземпляра 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 и here, мой код должен работать. Я наверняка CommandLineEventConsumer назвал {709782F3-E860-488E-BD8A-89FBC8C1495C}

И мой код не будет работать на IWbemServices::DeleteInstance, код ошибки 0x80041008 (один из параметров для вызова не является правильным).

Я был бы признателен, если бы кто-то ошибся в моем коде. Или, возможно, для этого требуются некоторые привилегии?

ответ

0

Я нашел два решения:

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% правильны.

2

Первый параметр для IWbemServices::DeleteInstance - BSTR. A BSTR отличается от строки C-стиля с кодировкой UTF-16 тем, что хранит аргумент с явной длиной. Хотя 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); 

В качестве альтернативы, так как вы уже используете ATL для CComPtr можно использовать 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 более прощает, когда отображаются недопустимые параметры.

+0

Он не работает ни с 'BSTR', ни' CComBSTR'. Также 'BSTR' набирается как' OLECHAR * ',' OLECHAR' как 'WCHAR',' WCHAR' как 'wchar_t'. Таким образом, в основном «BSTR» и «wchar_t *» совпадают. – ST3

+1

@ ST3: 'BSTR' и' wchar_t * '- это те же ** тип ** в C или C++, но с принципиально иной семантикой. A [BSTR] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms221069.aspx) представляет собой составной тип данных, который состоит из префикса длины, строки данных и терминатора. В качестве подсчитанной строки он может содержать встроенные символы NUL. С другой стороны, строка C-стиля имеет нулевое завершение и, следовательно, не может содержать символы NUL, поскольку она не поддерживает префикс прямой длины. Какой код ошибки вы получаете при использовании реального 'BSTR'? – IInspectable

+0

Код ошибки сохраняется, '0x80041008'. – ST3