Visual C++ ADO / LDAP / Exceptions



  • Hallo ich habe ein großes Problem mit ADO in Visual C++ 6.0

    Wenn ich die SQL Syntax ändere (also z.b. falsches LDAP Verzeichnis angebe) bekomme ich direkt eine Exception geworfen:
    Nicht abgefangene Ausnahme in TEST Final LDAP ADO.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception.

    Wenn ich einen falschen Benutzernamen oder Passwort angebe, gibts keine Exception und alle HRESULTS sind immer noch 0.

    Das Programm crasht ansonsten IMMER mit der exception.

    Irgend jemand eine Idee woher das kommen könnte und wie ich das abfange?

    Das Programm soll auf einen LDAP Server zugreifen und dort Usernamen und Passwörter auslesen können um diese mit einem Login des Users abzugleichen bzw. die Rechte auslesen.

    Vielleicht hat ja als Alternative jemand eine Idee, ob man das anders lösen kann.

    EDIT : irgendwo hab ich jetzt gesehen, dass es eine ältere Version von msado15.dll mit > 500 KB geben soll und in der 481 KB Version Probleme mit den Pointern auftreten. Aber keine Ahnung jetzt wo ich die >500 KB Version herbekommen soll.
    EDIT 2: hab die Datei gefunden - keine Änderung an den Exceptions.

    Gruß und danke für alle Antworten im voraus - egal ob hilfreich oder nicht :=)
    Jkuehl

    Code:

    #pragma warning(disable:4146)
    #import "msado15.dll" rename("EOF", "EndOfFile")
    #pragma warning(default:4146)
    using namespace ADODB;
    
    (.....)
    
    {
    	_ConnectionPtr	CnnPtr = NULL; 
    	_RecordsetPtr	RecPtr = NULL;
    
    	CString strhr;
    	HRESULT	hr = S_OK;
    
    	_bstr_t bstrPassword = "XXX(changed for forum post)";
    	_bstr_t bstrUserID = ">>>(changed for forum post)";
    	_bstr_t bstrQuery = L"SELECT 'UID' FROM 'LDAP://ZZZ(changed for forum post):389'";	
    	_bstr_t bstrConnectString = L"Provider=ADsDSOObject;Data Source=LDAP:ZZZ(changed for forum post):389";
    
    	try
    	{
    		hr = CoInitialize(NULL);   
    		hr = CnnPtr.CreateInstance(__uuidof(Connection),NULL); 
    		hr = CnnPtr->Open(bstrConnectString,bstrUserID,bstrPassword,adOptionUnspecified);		
    		hr = RecPtr.CreateInstance(__uuidof(Recordset),NULL); 
    		_variant_t vQuery(bstrQuery);
    		_variant_t vDispatch((IDispatch*)CnnPtr);
    		CnnPtr->AddRef();
    		hr = RecPtr->Open((LPCTSTR)bstrQuery,(LPCTSTR)bstrConnectString,adOpenDynamic, adLockOptimistic, adCmdUnknown);
    	}
    
    	catch( _com_error &e )
    	{
    		_bstr_t bstrSource(e.Source());
    		_bstr_t bstrDescription(e.Description());				
    		TRACE( "Exception thrown for classes generated by #import" );
    		TRACE( "\tCode = %08lx\n", e.Error());
    		TRACE( "\tCode meaning = %s\n", e.ErrorMessage());
    		TRACE( "\tSource = %s\n", (LPCTSTR) bstrSource);
    		TRACE( "\tDescription = %s\n", (LPCTSTR) bstrDescription);		
    		CnnPtr->Close();
    		RecPtr->Close();
    		CoUninitialize();
    	}
    
    	catch (...)
    	{
    		TRACE ( "*** Unhandled Exception ***" );
    	}
    }
    


  • Wo GENAU dein Fehler liegt kan ich dir nicht sagen. Nachfolgend jedoch einige
    Bemerkungen zu deinem Code:

    1.) Smartpointer müssen nicht initialisiert werden.

    _ConnectionPtr    CnnPtr = NULL; 
        _RecordsetPtr    RecPtr = NULL;
    

    sind somit überflüssig.

    2.) Wenn du schon (glücklicherweise) den HRESULT speicherst solltest du ihn
    auch konsequent auswerten.

    if (SUCCEEDED(hr))...
    

    3.) Und hier gehts dann ganz schief (mögliche Absturzursache)

    ((IDispatch*)CnnPtr
    

    Interface-Pointer dürfen/werden nicht gecastet. Verwende stattdessen
    QueryInterface() wie sich das gehört.

    4.) Es wäre schön wenn du (mögliche Absturzursache)

    CoUninitialize();
    

    in jedem Fall und nicht nur beim Fangen von Exceptions aufrufen würdest.

    5.)

    CnnPtr->Close();
            RecPtr->Close();
    

    Ist zwar ordentlich aber ähnlich überflüssig wie 1.



  • Ich muss zugeben, der Code oben ist unter aller Kanone, hab da viel rumprobiert :=) Deine Bemerkungen sind also alle korrekt, und normalerweise Programmiere ich auch nicht so. Glücklicherweise haben sich einige der Fehler schon erledigt. Ich werde zu gegebener Zeit nochmal posten, falls noch Fehler bestehen.

    das mit dem Cast werde ich mir jedoch mal genauer anschauen - das stand auf mehreren Seiten so - was ja nicht heißen muss dass es stimmt - daher werde ich mich selbst mal darüber informieren wie ich das erledigen soll.



  • Redhead schrieb:

    3.) Und hier gehts dann ganz schief (mögliche Absturzursache)

    ((IDispatch*)CnnPtr
    

    Interface-Pointer dürfen/werden nicht gecastet. Verwende stattdessen
    QueryInterface() wie sich das gehört.

    verstanden hab ich das jetzt dass Interface-Pointer nicht gecastet werden, aber wie verwende ich denn QueryInterface anständig? Irgendwo habe ich da einen Denkfehler drin und bekomme immer einen NULL-Zeiger.

    um es nochmal genauer zu formulieren: was muss ich bei **HIER** ändern damit ich die bestehende Connection für das Recordset benutzen kann? Habe auch hier zwecks übersichtlichkeit die hr Fehler nicht abgefangen.

    hr = CoInitialize(NULL);   
    hr = CnnPtr.CreateInstance(__uuidof(Connection),NULL); 
    hr = CnnPtr->Open(bstrConnectString,bstrUserID,bstrPassword,adOptionUnspecified);	
    hr = RecPtr.CreateInstance(__uuidof(Recordset));
    hr = RecPtr->Open(bstrConnectString, **HIER**, adOpenForwardOnly,adLockOptimistic,adOptionUnspecified);
    


  • MSDN schrieb:

    Open Method (Recordset) ADO
    Opens a cursor.

    Applies To

    Recordset

    Syntax

    recordset.Open Source, ActiveConnection, CursorType, LockType, Options

    Parameters

    **Source Optional. A Variant that evaluates to a valid Command object variable
    name, an SQL statement, a table name, or a stored procedure call.

    ActiveConnection Optional. Either a Variant that evaluates to a valid Connection
    object variable name, or a String containing ConnectionString parameters.**
    ...

    Ich würde die Variante mit dem ConnectionString verwenden. 🙂


Anmelden zum Antworten