Wmi mit C++ benutzen ?
-
Hallo,
normalerweise programmiere ich nicht mit C++, aber leider brache ich jetzt direkten zugriff auf einige Windows daten.Ich brache zugriff auf einige WMI daten, zb:
das bios:
http://msdn.microsoft.com/en-us/library/aa394077(VS.85).aspxLeider scheitere ich daran ein sinnvolles (funktionierendes) Beispiel zu finden, das nicht in VB Script ist
Ich hoffe jemand hier kann mir dabei helfen?
ps. ich hoffe das ist im richtigen Board, war mir nicht sicher.
-
Bitte sehr:
#include <windows.h> #include <wbemdisp.h> #include <tchar.h> #pragma comment(lib, "wbemuuid.lib") #pragma comment(lib, "oleaut32.lib") HRESULT GetPropertyString(ISWbemPropertySet *properties, LPWSTR name, BSTR *ppv) { ISWbemProperty *property; *ppv = 0; HRESULT hr; if (SUCCEEDED(hr=properties->Item(name, 0, &property))) { // #define VT_BSTR_ARRAY VT_BSTR|VT_ARRAY #define VT_VARIANT_ARRAY (VT_VARIANT|VT_ARRAY) // EDIT VARIANT vProp; vProp.vt = VT_EMPTY; // required if (SUCCEEDED(hr=property->get_Value(&vProp))) { if (vProp.vt==VT_BSTR && vProp.bstrVal) { *ppv = vProp.bstrVal; vProp.vt = VT_EMPTY; // disable VariantClear } else if (SUCCEEDED(hr=VariantChangeType(&vProp, &vProp, 0, VT_BSTR)) && vProp.bstrVal) { *ppv = vProp.bstrVal; vProp.vt = VT_EMPTY; } else if (vProp.vt==VT_BSTR && !vProp.bstrVal) { *ppv = SysAllocString(L"<L E E R>"); vProp.vt = VT_EMPTY; } else if ((vProp.vt==VT_VARIANT_ARRAY) && vProp.parray && ((int)SafeArrayGetDim(vProp.parray)==1)) // EDIT { // handle array of strings/numbers: string\nstring\n ... string\n WCHAR *append; VARIANT v; long a, cch=0; long count = vProp.parray->rgsabound[0].cElements; for (a=0; a<count; a++) { if (!SafeArrayGetElement(vProp.parray, &a, &v)) { //cch += (SysStringLen(v.bstrVal)+2); if (!VariantChangeType(&v, &v, 0, VT_BSTR)) // EDIT { cch += (SysStringLen(v.bstrVal)+2); } VariantClear(&v); } } *ppv = append = SysAllocStringLen(NULL, cch+1); if (!append) { hr = E_OUTOFMEMORY; } else { hr = S_OK; for (a=0; a<count; a++) { if (!SafeArrayGetElement(vProp.parray, (LONG*)&a, &v)) { //append = &append[swprintf(append, L"%s\r\n", v.bstrVal)]; // EDIT if (!VariantChangeType(&v, &v, 0, VT_BSTR)) { append = &append[swprintf(append, L"%s\r\n", v.bstrVal)]; } VariantClear(&v); } } } } else { hr = E_FAIL; } VariantClear(&vProp); } property->Release(); } return hr; } void ShowError(HRESULT hr, LPTSTR info) // EDIT { TCHAR text[300]; int cch = _sntprintf(text, 300, TEXT("%s failed with error 0x%.8X\n"), info, hr); FormatMessage(0x000010FF, 0, hr, 0, &text[cch], 300-cch, 0); MessageBox(0, text, 0, MB_ICONHAND); } extern"C" int main() { CoInitialize(0); ISWbemServices *services = 0; ISWbemObjectSet *set = 0; IUnknown *unk = 0; IEnumVARIANT *enumv = 0; VARIANT v; HRESULT hr; #define EXIT_DO(x,y) {x=0; ShowError(hr,y);break;} do { if (FAILED(hr=CoGetObject(L"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2", NULL, IID_ISWbemServices, (void**)&services))) EXIT_DO(services, TEXT("CoGetObject")); if (FAILED(hr=services->ExecQuery(L"Select * from Win32_BIOS", L"WQL", 0, NULL, &set))) EXIT_DO(set, TEXT("ExecQuery")); if (FAILED(hr=set->get__NewEnum(&unk))) EXIT_DO(unk, TEXT("get__NewEnum")); if (FAILED(hr=unk->QueryInterface(IID_IEnumVARIANT, (void**)&enumv))) EXIT_DO(enumv, TEXT("IEnumVARIANT")); // now use IF or WHILE if (!enumv->Next(1, &v, NULL)) { if (!VariantChangeType(&v, &v, 0, VT_UNKNOWN)) { ISWbemObject *object; if (!v.punkVal->QueryInterface(IID_ISWbemObject, (void**)&object)) { ISWbemPropertySet *properties; if (!object->get_Properties_(&properties)) { BSTR bstrText; if (FAILED(hr=GetPropertyString(properties, L"BIOSVersion", &bstrText))) { ShowError(hr, TEXT("GetPropertyString")); } else { MessageBox(0, bstrText, L"Bios Version", 0); SysFreeString(bstrText); } properties->Release(); } object->Release(); } } VariantClear(&v); } } while (0); #define Release(x) if (x) x->Release(); Release(enumv); Release(unk); Release(set); Release(services); CoUninitialize(); return 0; }
-
Super
das funktioniert soweit,
habe den code jetzt etwas an meine Vorlieben angepasstEine frage dazu noch: Gibt es einen Grund warum du alle Fehler Manuell abfragst statt ein try catch darumzukleben?
Programmiere normalerweise mit Java, und habe gesehen das es das in c++ auch gibt.
-
Wo werden hier den Exceptions geworfen, die man abfangen könnte?
-
Naja dachte überall sozusagen,
dachte die sind wie die in Java...
Da hat man normalerweise bei fehlerfällen irgetwo was was ne Exception wirft.
-
Code updated, habe keine Ahnung warum "BIOSVersion" mit BSTR|ARRAY funtzte. Wahrscheinlich preprocessor bug mit x|y ohne ().
Empire Phoenix, es gibt keinen Grund, das war nur ein Beispiel. Du kannst ShowError immer mit throw ersetzen.
(Reale) Exceptions kann man abfragen nur von IDispatch::InvokeHRESULT Invoke( DISPID dispIdMember, // z.B. services->GetIDsOfNames(array(L"ExecQuery")) =pseudocode REFIID riid, // IID_NULL LCID lcid, // LOCALE_NEUTRAL WORD wFlags, // DISPATCH_METHOD, DISPATCH_PROPERTYGET... DISPPARAMS* pDispParams, // arguments for ExecQuery method VARIANT* pVarResult, // optional EXCEPINFO* pExcepInfo, // opt. will be filled in if DISP_E_EXCEPTION is returned unsigned int* puArgErr // opt. returned when DISP_E_TYPEMISMATCH or DISP_E_PARAMNOTFOUND is returned ); EXCEPINFO excep; if ((hr=object->Invoke(..., &excep, NULL)) == DISP_E_EXCEPTION) { AfxThrowOleDispatchException(excep.wCode, excep.bstrDescription, excep.dwHelpContext); } else if (FAILED(hr)) { throw hr; }
Beispiel: XLCLIENT: Automatisierungsclient für Excel
AutoWrap() - Automation helper function
-
Habe jetzt alles soweit zum laufen gebracht,
dank dir