C++ MFC CDatabase Unhandled Exception, Access violation when calling Open or OpenEx MS Access

bowser17
bowser17 used Ask the Experts™
on
When trying to open a MS Access database .mdb using C++ MFC CDatabase object, i try using Open or OpenEx, and i get:
Unhandled exception at 0x00000000 in MPUtilD.exe: 0xC0000005: Access violation reading location 0x00000000.

The mysterious part is this code was working, and now it doesn't.  I thought it may be some database change i made, maybe corrupting something, but i tried repair and compact.  I even tried an older version of the database from a  backup when i know for sure it was working.  Nothing!  I've changed the path, the name of the database, tried slight variations of the connection string... nothing works.  Im super frustrated.

Here is how i build the connection string:
CDatabase db;
CString cnStr;
cnStr.Format("ODBC;DRIVER={MICROSOFT ACCESS DRIVER (*.mdb)};DSN='';DBQ=%s",sFile);
db.OpenEx(cnStr);

sFile is the path to the database, and is passed in.  I check the value of cnStr prior to stepping through OpenEx, and verify the string is good.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2006

Commented:
Have u got all the latest drivers in place? MDAC and all

Also try a decompile, see if that helps http://www.granite.ab.ca/access/decompile.htm

Compact/Repair doesnt always repair corrupted databases, thats if u have one
so try this

create a brand new database then create a new table there. Does accessing that work?
If so then try importing some tables from the old db into this new db. Does accessing them work?

Another recovery method is to import objects from old db to new db

Author

Commented:
I believe my MDAC is up to date, as i mentioned, this worked before, and i actually started a new project and was able to open the DB from the new project with that code.
I dont have any VBA in the database, but i guess i could still try the decompile.  I have Access 2003, however it says in the title bar of the window, Access 2000 file format.  I had also tried the new database, blank, and with tables imported.  None of that works.  Would could have changed in my project?  I am at a loss....  i guess i may be forced to recreate the project from scratch

Author

Commented:
I would like to rephrase the question, as this all works on another computer, so its obviously some sort of config, or and environment change.  If possible, can someone give some code method on how to determine what the error actually is?  I tried using a try catch, but the GetLastError = 0.  the try was:

try
{
catch(...)
{
  DWORD le = GetLastError();
}
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Top Expert 2006

Commented:
its been a while since Ive done C++ especially using visual c++

lets try something a little easier. A bit of vb. Dont worry u dont need vb installed.
Since u have access, open up a new database then go into modules (alt-f11)
create a new module (right click on project explorer and select insert module

lets try this, note u may need to add the DAO reference. (in vba code window, go to Tools/Reference and select Microsoft DAO Object Library v3.6)

public sub TestOpenDBFromAltSource()
    dim db as dao.database
    dim rs as dao.recordset

    set db = DBEngine(0).OpenDatabase("c:\mydb.mdb")
    set rs=db.openrecordset("select * from sometable")
    if rs.eof = false then
        msgbox "got record " & rs.fields(0).value
    else
        msgbox "no recs"
    end if
    rs.close
    set rs=nothng
    db.Close
    set db=nothing
end function



Note, this is just a test. I want to see what happens if u open your database using another source.


regarding C++, its something like this

CDatabase db;
CString SqlString;
CString sDriver = "MICROSOFT ACCESS DRIVER (*.mdb)";
CString sDsn;
CString sFile = "c:\mydb.mdb";
      
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);

try {
    db.Open(NULL,false,false,sDsn);
}
catch (CDBException, e)
{
    AfxMessageBox("Got Error : " + e->m_strError);
}
end_catch;

Author

Commented:
the vb test works, and the C++ wont catch the CDBException, or CException even, only ...
Top Expert 2006

Commented:
ok, that means your database is fine, I would say so since it works fine with vb

with C++, did u try fetchng data? example I gave just did a open

Author

Commented:
As the first message states, its throwing an unhandled exception on the open method.  Im not sure what i can do at this point...
Top Expert 2006

Commented:
so its falling over on

db.Open(NULL,false,false,sDsn);


what are the other parameters for db.Open? there are 4, last one being your connection string

Author

Commented:
i dont recall, but this used to work, and it actually works on the same amchine in a new project which is strange.  I have something else im going to try to fix, maybe i'll get lucky and it will solve that too... (but probably not).

Commented:
Here is what I have.

1.) you will have to create a database.  I've used Access but that is all that has been available to me.

2.) inside the control panel there is an icon odbc data source.  When you open this there is a tab for user DSN.  Press the add button.  This will allow you to select the database that you created in step 1.

3.) here is a short program for accessing the database.  Here the example was for a simple database containing a last name and first name.
#include <afx.h>
#include <afxdb.h>
#include <conio.h>

void main()
{
  CDatabase *pMyDbase=new CDatabase;
  CRecordset *pMyRecord;
  CString sSQL="SELECT Last, First FROM Person ";
  CString sSQL1;
  CString sFirst;
  CString sSecond;
  CDBVariant dbVFirst;
  CDBVariant dbVSecond;

  sSQL1.Format("WHERE Last = %s;", "Flinstone");
  try
    {
      pMyDbase->OpenEx(_T("DSN=Database"),CDatabase::openReadOnly);
      pMyRecord= new CRecordset(pMyDbase);
      pMyRecord->Open(CRecordset::snapshot,sSQL+sSQL1);
      while(!pMyRecord->IsEOF())
      {
        pMyRecord->GetFieldValue((short)0, sFirst);
        pMyRecord->GetFieldValue(1, dbVSecond);
        pMyRecord->MoveNext();
      }
      pMyDbase->Close();
      getch();
    }
    catch(...)
    {
      pMyDbase->Close();
    }
}
The short on the zero of first element is required.  Why I don't know.  It came down from the microsoft engineers.

Hope that is of some help.  Good luck and good coding.
Gregg


Author

Commented:
Ok, not sure if you guys are still watching but i've managed to trace the exception into the tidtable.c code:

_ptiddata __cdecl _getptd (
        void
        )
{
        _ptiddata ptd;
        DWORD   TL_LastError;


        TL_LastError = GetLastError();
        if ( (ptd = FLS_GETVALUE(__tlsindex)) == NULL ) {
            /*
             * no per-thread data structure for this thread. try to create
             * one.
             */
            if ( ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL) &&
                FLS_SETVALUE(__tlsindex, (LPVOID)ptd) ) {

                /*
                 * Initialize of per-thread data
                 */

                _initptd(ptd);

                ptd->_tid = GetCurrentThreadId();
                ptd->_thandle = (uintptr_t)(-1);
            }
            else
                _amsg_exit(_RT_THREAD); /* write message and die */
            }

        SetLastError(TL_LastError);


        return(ptd);
}

the exception happens on this line:
 if ( (ptd = FLS_GETVALUE(__tlsindex)) == NULL )

I cannot trace anymore into it.  The only thing i've read regarding this is to make sure i am using the correct version of the CRT libs, which i believe i am, /MTd in all libs and exes.

Commented:
are you trying to open the actual access database directly? I don't know that you can do this using an ODBC connection.  The only way that I have successfully opened an access database directly is ole Database elements.  Copy the source I pushed up and see if it works for you.  At least you will be connecting.  I will see what I can do about creating an ole example.... It I can find some old source.
Mean while try what I pushed up.

Author

Commented:
I don't know if my previous messages are unclear, but the code i have right now used to work.  I have since made some small changes to it and to other libs.  Now it does not work.  When i start a brand new project, use the same code to open the database, it works.  Im not sure what to do next.  I am trying to avoid a complete teardown.
Commented:
Well, apparently even Microsoft couldn't solve the issue.  I started over, and now it works.  Must have been something in Visual studio.

Author

Commented:
I'd like to close the question since no one answered.  Thanks all for trying.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial