【MFC】ODBC 接続の IM002 エラー:32bit / 64bit ドライバ不一致の確認と対処

【MFC】ODBC 接続の IM002 エラー:32bit / 64bit ドライバ不一致の確認と対処

ビルド構成を x64 に変えた、あるいは 32bit のまま運用しているアプリで、ODBC 接続だけが失敗することがあります。この記事では、アプリと ODBC ドライバの 32bit / 64bit が食い違ったときに出る IM002 エラーを、確認する場所と対処の順に扱います。DSN の設計やドライバ個別の設定値までは踏み込みません。


目次

まず確認するもの

症状最初に見る場所
IM002 でドライバが見つからないアプリのビルド構成(Win32 / x64)と、同じビット数のドライバ一覧
x64 に変えた途端に接続できない64bit 側のドライバ一覧に、同名のドライバがあるか
ODBC アドミニストレーターに DSN が見えているのに失敗するその DSN が User DSN かどうか。User DSN は両方の一覧に出るため、見えていても接続できないことがある
接続文字列をコピーしたら失敗したDRIVER={...} の名前が、そのビット数で登録されている綴りと一致するか

アプリのビット数と ODBC ドライバのビット数は、必ず一致している必要があります。32bit アプリは 32bit ドライバだけ、64bit アプリは 64bit ドライバだけを読み込みます。これは実行ファイルと DLL のビット数が一致しないと起動しない仕組みと同じ理由で、0xc000007b エラーと根が同じ問題です。


IM002 は何を言っているのか

ビット数が食い違うと、CDatabase::OpenExCDBException を投げます。32bit ビルドで 64bit にしか無いドライバを指定したときの出力です。

[接続失敗] CDBException
  m_strError    : データ ソース名および指定された既定のドライバーが見つかりません。

  m_strStateNativeOrigin : State:IM002,Native:0,Origin:[Microsoft][ODBC Driver Manager]

報告元が ODBC Driver Manager である点が手がかりになります。データベースに届く前の段階、つまりドライバを探す段階で止まっています。DB サーバーやファイルの問題ではありません。

ドライバが見つからない理由は、登録先がビット数ごとに分かれているからです。片方に入れても、もう片方からは見えません。

対象レジストリキー
64bit ドライバHKLM\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers
32bit ドライバHKLM\SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI\ODBC Drivers

コマンドプロンプトで、それぞれの一覧を確認できます。

:: 64bit ドライバ一覧
reg query "HKLM\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"

:: 32bit ドライバ一覧
reg query "HKLM\SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI\ODBC Drivers"

見落としやすいのは、ドライバ名そのものが違うこと

「Access のドライバは入っている」と思っていても、32bit 側と 64bit 側で登録されている名前が違うことがあります。検証機で両方の一覧を取得した結果が次です。

64bit 側に登録されていた名前32bit 側に登録されていた名前
Microsoft Access Driver (*.mdb, *.accdb)Microsoft Access Driver (*.mdb)
Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)Microsoft Excel Driver (*.xls)
Microsoft Access Text Driver (*.txt, *.csv)Microsoft Text Driver (*.txt; *.csv)

64bit 側は Access Database Engine(ACE)が入れたドライバ、32bit 側は Windows に元から入っている古いドライバです。名前が別物なので、64bit アプリで動いていた接続文字列を 32bit ビルドへ持っていくと、綴りが一致せず IM002 になります。エラーは「ドライバが無い」と読めますが、実際は「その名前のドライバが、このビット数には登録されていない」という意味です。


同じコードを x64 と Win32 でビルドして確かめる

同一のソースを両方の構成でビルドし、同じ接続文字列で試すと違いがはっきりします。ドライバ名には 64bit 側にしか無い Microsoft Access Text Driver (*.txt, *.csv) を指定し、実行ファイルと同じフォルダの CSV を読みます。

この検証機には 64bit 版の ACE だけが入っています。32bit 版の ACE も入っている環境では、Win32 ビルドでも接続に成功して IM002 は出ません。手元で試す前に、先ほどの reg query で 32bit 側の一覧を確認してください。

CString strConn;
strConn.Format(_T("DRIVER={%s};DBQ=%s;"),
               _T("Microsoft Access Text Driver (*.txt, *.csv)"),
               (LPCTSTR)GetExeDir());

CDatabase db;
try
{
    db.OpenEx(strConn, CDatabase::noOdbcDialog);
    CRecordset rs(&db);
    rs.Open(CRecordset::forwardOnly, _T("SELECT id, name FROM sample.csv"),
            CRecordset::readOnly);
    // 取得処理
}
catch (CDBException* e)
{
    // ビット数が一致しないと、ここで IM002 が報告される
    _tprintf(_T("%s\n"), (LPCTSTR)e->m_strStateNativeOrigin);
    e->Delete();
}

x64 ビルドは接続でき、CSV の中身まで読み取れました。

--------------------------------------------------
プロセスのビット数 : 64 bit (sizeof(void*)=8)
使用する DRIVER    : Microsoft Access Text Driver (*.txt, *.csv)
--------------------------------------------------
接続文字列 : DRIVER={Microsoft Access Text Driver (*.txt, *.csv)};DBQ=C:\temp\178_OdbcBitness\x64;

[接続成功] ドライバのビット数が一致しています。
--- sample.csv の中身 ---
  id=1, name=Alice
  id=2, name=Bob
  id=3, name=Carol

同じソースの Win32 ビルドは、接続の時点で失敗します。32bit 側にこの名前のドライバが無いためです。

--------------------------------------------------
プロセスのビット数 : 32 bit (sizeof(void*)=4)
使用する DRIVER    : Microsoft Access Text Driver (*.txt, *.csv)
--------------------------------------------------
接続文字列 : DRIVER={Microsoft Access Text Driver (*.txt, *.csv)};DBQ=C:\temp\178_OdbcBitness\x86;

[接続失敗] CDBException
  m_strError    : データ ソース名および指定された既定のドライバーが見つかりません。

  m_strStateNativeOrigin : State:IM002,Native:0,Origin:[Microsoft][ODBC Driver Manager]

コードも接続文字列も同じで、違うのはビルド構成だけです。


odbcad32.exe と DSN の見え方

ODBC アドミニストレーターも 2 つあります。フォルダ名と中身が逆に見えますが、System32 が 64bit 用、SysWOW64 が 32bit 用で正しい対応です。

ツールパス対象
64bit 版C:\Windows\System32\odbcad32.exe64bit ドライバ / 64bit System DSN
32bit 版C:\Windows\SysWOW64\odbcad32.exe32bit ドライバ / 32bit System DSN

スタートメニューから「ODBC データ ソース」を開くと、どちらを起動したのか分かりにくいことがあります。確実に区別するには、上記のパスを直接指定して起動します。

DSN の見え方は種類によって違うので注意が必要です。System DSN はビット数ごとに分かれていて、32bit 用に作ったものは 64bit 版の一覧には出ません。一方 User DSN は分かれておらず、両方の一覧に出ます。ただし一覧に出ることと接続できることは別です。32bit ドライバを使う User DSN は 64bit アプリからも見えますが、接続すると IM002 になります。「アドミニストレーターには見えているのに繋がらない」ときは、この状態を疑ってください。


症状ごとの対処

症状原因対処
64bit アプリで Access のファイルに接続できない64bit 版 ACE が未インストールMicrosoft Access Database Engine の 64bit 版を入れる
Win32 から x64 に変えたら接続できなくなった64bit 側に同名ドライバが無い、または System DSN が 32bit 側にしか無い64bit 側の一覧を確認し、必要なら 64bit 版 odbcad32.exe で DSN を作る
DSN レス接続でドライバ名エラーになるドライバ名の綴りが、そのビット数の登録名と違うreg query で登録名をそのまま写す
User DSN が見えているのに IM002 になるその DSN が、アプリと違うビット数のドライバを指しているアプリと同じビット数のドライバを入れるか、その DSN を作り直す
64bit 版 ACE のインストーラが止まる32bit 版 Office が入っているとブロックされることがあるOffice のビット数を確認する。合わせられない場合はアプリを Win32 ビルドのままにする

どちらのビット数に合わせるかは、入れられるドライバ側の制約で決まることが多いです。ドライバを 32bit しか用意できない場合、そのプロセスから直接つなぐ限りは Win32 ビルドに揃えることになります。


まとめ

  • IM002 の報告元が ODBC Driver Manager なら、DB ではなくドライバを探す段階で止まっています
  • 32bit アプリは 32bit ドライバ、64bit アプリは 64bit ドライバだけを読み込みます
  • ドライバの登録先は ODBCINST.INIWOW6432Node\ODBC\ODBCINST.INI に分かれています
  • 同じ製品でも 32bit 側と 64bit 側で登録名が違うことがあるため、接続文字列の綴りは登録名をそのまま写します
  • odbcad32.exeSystem32 が 64bit 用、SysWOW64 が 32bit 用です
  • System DSN はビット数ごとに分かれ、User DSN は両方から見えます。見えていても接続できるとは限りません
  • ビルド構成を Win32 から x64 に変えたら、ドライバと DSN を同じビット数で用意し直します
目次