今の会社では業務を補完するためにAccessで作られたアプリケーションが大量に存在し、それらをシステム部署で管理できていないためカオスな状況なのですが、最近、Runtimeで動かしている特定のAccessアプリケーションが特定の端末だけでエラーになり、その原因特定に苦労したので紹介しておきます。
エラーの詳細
- Accessアプリケーションの起動は出来るが特定の操作でエラーが出てAccessが強制終了。
- エラーメッセージは「実行時エラーが発生したため、このアプリケーションの実行は中断しました。」
- 他のAccessアプリケーションは正常に動作し、ODBCデータソースに必要な設定は入っているはず。
原因特定、調査のために試したこと
ネットで調べながら色々と試しました。
WindowsUpdateによる不具合
ちょうど少し前にマイクロソフトがやらかして、更新クエリや追加クエリなど、データへの変更が発生するクエリを実行するとエラーなるという不具合を含んだ、ウイルスのようなパッチを配信しました。
- Access2010 KB4484127
- Access2013 KB4484119
- Access2016 KB4484113
上に書いたように当社の環境はAccessのアプリケーションがばらまかれているので、アップデートの配信直後はエラー報告が多発していましたが、原因と対応方法(KBのアンインストール)を案内してからは落ち着いておりました。
今回のエラーが発生して真っ先に疑ったのがこのパッチのアンインストール漏れです。
パッチが適用されているかプログラムの一覧から確認すると・・・入っていない。
また別のケースのようです。
VBA エディタでコンパイル実施
ネットで調べると、通常のAccessがインストールされた環境ではプログラムに軽い不備があっても動くが、Runtime上ではエラーになるケースがあるとのこと。
VBAエディタのメニューに「コンパイル」という項目があり、それを実行すればチェックが出来るとのこと。
10年以上Accessを触ってきましたが、コンパイルが出来るなんて初めて知りました・・・。
早速実行してみると、一ヵ所だけ不備がありました。
感心しながらも修正し、エラーが出る端末で修正済みのAccessアプリケーションを動かすと・・・治ってない。これも違いました。
Runtimeの再インストールやバージョン変更
他の端末では発生していないということもあり、インストールされているRuntime自体がおかしくなっている、または2010や2013などのバージョン違いによる相性とかあるのか?などと考えて、現在使用していたRuntimeの再インストールや異なるバージョンのRuntimeをインストールを実施して、再度動作を確認するが・・・改善しない。
RuntimeモードでのAccessアプリケーションの起動
これも今回のトラブルで初めて知ったのですが、Access本体がインストールされており、Runtimeがインストールされていない端末で、AccessファイルをRuntimeモードで起動できるやり方がありました。
コマンドプロンプトでAccess.exeを実行し、実行時にオプションとして /runtime “Accessファイルのフルパス”を渡します。
■コマンド実行例
MSACCESS.EXE /runtime "C:\test.accdb"
環境によっては、コマンドの最初のMSACCESS.EXEが見つからないと言われるかも知れないので、その場合はProgram Files配下のOfficeインストール先のMSACCESS.EXEを探して、フルパスでMSACCESS.EXEを指定して実行してください。
因みにこのRuntimeモードは、Accessアプリケーションの開発者がRuntimeユーザーにAccessアプリケーションを配布する際に、どのような見え方になって、そのような挙動になるのかを確認するために使用するモードのらしいです。
これでエラーが発生している端末と同じように自端末で再現が取れると踏んだのですが、このRuntimeモードで起動しても自端末ではエラーは発生せず・・・。
原因の特定ができた対応方法
エラーが発生する箇所でエラー処理を入れる
何でこんな当たり前のことを思い付かなかったんだろうか。
Runtimeではプログラム内でエラーが発生した場合にVBAエディタ画面が出せないので強制的にAccess自体が終了しているですが、エラーの発生箇所自体はある程度特定出来ているので、その処理の近辺にエラー処理を入れておけば、その原因がわかるかも知れません。
そこで、該当の幾つかの処理の近辺に以下のコードを仕込んでRuntime上で動かしてみました。
'エラーハンドリング開始します。 On Error GoTo OnError 'エラーが発生していると思われる処理を 'この範囲に含めます。 'エラーハンドリング終了します。 On Error GoTo 0 'エラー発生時はここに飛びます。 OnError: msgbox "エラー番号:" err.Number & " エラー内容:" & err.Description
このようにエラー処理を入れてAccessアプリケーションを実行したところ、狙った通りエラーの原因がメッセージボックスに表示されました。
因みに私の場合では、必要なDSNが対象の端末のODBCデータソースに登録されていませんでした。
当記事の最初に書いた通り、リンクテーブルマネージャーでリンクテーブルが作られているODBCデータソースは確認していたのですが、どうもAccessアプリケーション内で使われていたパススルークエリに埋め込まれていた接続文字列内にて別のDSNを使うように指定されており、それが原因でした。
まとめ
- 原因不明のエラーが出る場合は落ち着いて基本に立ち返りエラーをハンドルする。
- 可能であれば極力端末のODBCデータソース設定に依存しない実装を心掛ける。
- トラブルの予防とトラブル発生時の切り分けのために社内のAccess本体やRuntimeのバージョンは統一する。
ネットで今回のエラーメッセージ内容で検索すると結構ヒットするので、このエラーが出て困っている人も多いかと思います。
今回の記事が誰かの参考になるようでしたら幸いです。
ではでは、今回も読んで頂きましてありがとうございました。