CoInitializeEx() schlägt fehl
-
Hallo, um einen alten Thread nicht zu sprengen, hier mein Problem:
Bei mir schlägt das Initialisieren mit CoInitializeEx()fehl, soll heißen FAILED(hres) tritt ein.
HRESULT hres; // Step 1: -------------------------------------------------- // Initialize COM. ------------------------------------------ hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { ShowMessage("Failed to initialize COM library."); return -1; // Program has failed. }Der Code im Ganzen steht auf http://msdn2.microsoft.com/en-us/library/aa390423(VS.85).aspx
geändert hate ich lediglich die Ausgabe der Fehlercodes mittels ShowMessage() (wobei ich den hex-Fehlercode nicht auf die schnelle reinbekommen habe) und die _bstr_t durch TOleString (mit #include "utilcls).
Dem Projekt habe ich folgende Bibliotheken hinzugefügt:
cimwin32.dll
kernel32.lib
psapi.lib
WbemUuid.lib (aus dem <bccsdk> von http://sourceforge.net/projects/bccsdk/)Kann es evtl zu einer Inkonsistenz mit einem anderen Header gekommen sein?
#include <vcl.h> #pragma hdrstop #include "Unit1.h" #include "Psapi.h" #include <windows.h> #include <tlhelp32.h> //TOleString #include "utilcls.h" #define _WIN32_DCOM #include <iostream> using namespace std; #include <comdef.h> #include <Wbemidl.h> # pragma comment(lib, "wbemuuid.lib")Kompilieren und ausführen lässt sich das Projekt ohne Fehler oder Hinweise seites des BCB, bis halt an besagter Stelle die Exception eintritt.
Woran kann das liegen das CoInitializeEx() fehlschlägt?
Mit freundlichen Grüßen,
Tippo
-
Schau dir die Dokumentation zu CoInitializeEx an; wie dort steht, gibt es sechs mögliche Rückgabewerte. Das FAILED()-Makro überprüft, ob der übergebene Wert negativ ist; das ist nur für die Werte mit E_, also E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED und RPC_E_CHANGED_MODE der Fall. Du solltest deinen Rückgabewert in diesem Fall genauer überprüfen.
-
Ok, ich hab mir jetzt den Rückgabewert der Funktion abgefangen und mal ausgeben lassen:
-2147417850HRESULT ist ja vom Typ LONG, die MSDN meint ja:
his function supports the standard return values E_INVALIDARG, E_OUTOFMEMORY, and E_UNEXPECTED, as well as the following:
S_OK
The COM library was initialized successfully on the calling thread.
S_FALSE
The COM library is already initialized on the calling thread.
RPC_E_CHANGED_MODE
A previous call to CoInitializeEx specified a different concurrency model for the calling thread, or the thread that called CoInitializeEx currently belongs to the neutral threaded apartment.
Aber inwiefern hilft mir das jetzt weiter? Ich möchte die Funktion ja gerne benutzen... Was sagt mir der Rückgabewert denn nun, was mache ich falsch?
Guten morgen,
Tippo
-
switch/case !?
-
öhm naja, es bringt mir ja nichts, das ich die Fehlernummer kenne, ich möchte ja gerne das die Funktion initialisiert,
ich finde halt nur leider nicht warum?!
hres = CoInitializeEx(0, COINIT_MULTITHREADED); switch (hres) { case S_OK: ShowMessage("S_OK"); case S_FALSE: ShowMessage("S_FALSE "); case RPC_E_CHANGED_MODE: ShowMessage("RPC_E_CHANGED_MODE"); }Ok, dann tritt ein "RPC_E_CHANGED_MODE", das ist schon mal besser als der Zahlenwert von vorhin, danke Jansen!
MSDN schrieb:
RPC_E_CHANGED_MODE
A previous call to CoInitializeEx specified a different concurrency model for the calling thread, or the thread that called CoInitializeEx currently belongs to the neutral threaded apartment.
Leider kann ich damit nichts anfangen, soll das denn vielleicht heissen, dass die CoInitializeEx() schon aufgerufen wurde?
MfG und besten Dank voraus,
Tippo
-
-
Okay, also wenn ich das richtig verstehe muss der Aufruf der auf die COM zugreift diese sozusagen auch wieder schließen.
Um auszuschließen das ein anderer Programmteil auf diese zugreift, habe ich ein neues Projekt gemacht, und nur meine Funktion und einen Button reingebaut.//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include <objbase.h> #include <wbemcli.h> #include <utilcls.h> #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- int GetHardwareInformation(void) { HRESULT hres; // Step 1: -------------------------------------------------- // Initialize COM. ------------------------------------------ hres = CoInitializeEx(0, COINIT_MULTITHREADED); switch (hres) { case S_OK: ShowMessage("S_OK"); case S_FALSE: ShowMessage("S_FALSE "); case RPC_E_CHANGED_MODE: ShowMessage("RPC_E_CHANGED_MODE"); } // Step 2: -------------------------------------------------- // Set general COM security levels -------------------------- // Note: If you are using Windows 2000, you need to specify - // the default authentication credentials for a user by using // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ---- // parameter of CoInitializeSecurity ------------------------ hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { ShowMessage("Failed to initialize security. Error code"); CoUninitialize(); return -1; // Program has failed. } // Step 3: --------------------------------------------------- // Obtain the initial locator to WMI ------------------------- IWbemLocator *pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { ShowMessage("Failed to create IWbemLocator object."); CoUninitialize(); return -1; // Program has failed. } // Step 4: ----------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices *pSvc = NULL; // Connect to the root\cimv2 namespace with // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( TOleString(L"ROOT\\CIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if (FAILED(hres)) { ShowMessage("Could not connect. Error code = 0x"); pLoc->Release(); CoUninitialize(); return -1; // Program has failed. } //cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl; // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { ShowMessage("Could not set proxy blanket. Error code = 0x"); pSvc->Release(); pLoc->Release(); CoUninitialize(); return -1; // Program has failed. } // Step 6: -------------------------------------------------- // Use the IWbemServices pointer to make requests of WMI ---- // For example, get the name of the operating system IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( TOleString("WQL"), TOleString("SELECT * FROM Win32_OperatingSystem"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { ShowMessage("Query for operating system name failed."); pSvc->Release(); pLoc->Release(); CoUninitialize(); return -1; // Program has failed. } // Step 7: ------------------------------------------------- // Get the data from the query in step 6 ------------------- IWbemClassObject *pclsObj; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; } VARIANT vtProp; // Get the value of the Name property hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); ShowMessage(vtProp.bstrVal); VariantClear(&vtProp); } // Cleanup pSvc->Release(); pLoc->Release(); pEnumerator->Release(); pclsObj->Release(); CoUninitialize(); return 0; // Program successfully completed. } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int i = GetHardwareInformation(); ShowMessage(IntToStr(i)); } //---------------------------------------------------------------------------Aber jetzt wirds haarig... Der Aufruf liefert immer noch "RPC_E_CHANGED_MODE" zurück, aber ich hab doch vorher gar keinen anderen Aufruf?!
Im Folgenden öffnet sich dann das "CPU" Fenster:http://imagehoster.us/uploads/94a7e067f9.jpg
Dem neuen Projekt wurden keine anderen Bibliotheken hinzugefügt, nur die o.g. includes, die header-Datei blieb unbelassen.
Danke für jede Idee!
TippoEdit:
Also sry das ich so viel Code gepostet habe, ich hab die Microsoft Version jetzt verworfen.
Auf http://codecentral.borland.com/Item.aspx?id=19443 (danke Jansen für die Links) habe ich Code gefunden der wesentlich einfacher ist, so das ich ihn besser nachvollziehen konnte, und der ohne die ganzen extra Bibliotheken klar kommt. Aber vlt seht ihr ja oben noch einen dilettantischen Fehler an dem alles scheitert.
-
Ich hatte vor kurzem ein ähnliches Problem mit CoInitialize().
Es war letzten Endes kein fehler in meinem Programm sondern ka. wo.
Geholfen hat jedenfals bereinigen des Projekts und neu-compilieren.Mfg XBert