はじめに
これは、C# Advent Calendar 2020の11日目の記事になります。
予定では漢数字のソートなどについての記事にしようと思ってたのですが、検証用プログラムが間に合わなかったため別の機会とします。「その2」はまだ空き日があるようですし。
最近のPCは64bitであり、Windows OS側も64bitとなっているのが一般的になりました。
Officeのアプリケーションを操作するのに、Microsoft.Office.Interop.XXXXX を参照したとして、次の環境で動作するの? というのが今回の記事になります。
プラットフォーム ターゲット | Office ビット | 動作 |
---|---|---|
AnyCPU(64bit) | Office 64bit | 問題なし |
AnyCPU(64bit) | Office 32bit | ? |
x86 | Office 32bit | 問題なし |
x86 | Office 64bit | ? |
64bit版WindowsのJet.OLEDB.4.0問題
2018年からサーバーリプレース作業でデータベースを Oracle 11g から PostgreSQL 9.6 に移行しました。
OracleからPostgreSQL移行について
ユーザーに提供しているアプリケーションの1つにC#のアプリケーション(2011年頃に作られたもの)があり、印刷機能は2種類で1つはCrystalReport(Visual Studio 2008のバンドル版)を使用したもの、もう1つはAccessのレポート(mdb)を使用していました。
Accessのレポートは、ユーザー側でレポートのデザインを変更できるということで採用されているようです。
レポート用のデータをmdbファイルに登録する必要があるのですが、64bit版Windowsでは「Microsoft.Jet.OLEDB.4.0」が提供されていません。
AnyCPU(64bit)でmdbを操作しようとすると「'Microsoft.Jet.OLEDB.4.0' プロバイダはローカルのコンピュータに登録されていません。」というエラーになります。
64bit版Windowsでの「Microsoft.Jet.OLEDB.4.0」について
プロバイダー部分を「Provider=Microsoft.Jet.OLEDB.4.0」 → 「Provider=Microsoft.ACE.OLEDB.12.0」に書き換えるといいのですが、この場合には「Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント」のインストールが必要になります。
昨今のOffice 365でも、Microsoft Access は標準でインストールされるのですが、クイック実行形式の Office 製品をインストールした場合、OLEDB プロバイダーは登録されないのです。
クイック実行形式の Office をインストールすると Office 以外のアプリケーションから ODBC / OLEDB が利用できない
ClickOnceアプリケーションということもあって、別途「Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント」のインストールさせるのも、なんだしなということもあり別案で行くことにしました。
64bit版Windowsには32bitプログラムを動かす仕組み「WOW64」がありますので、その環境内でなら「Microsoft.Jet.OLEDB.4.0」が使用することができます。そのためプラットフォームターゲットをAnyCPUからx86にを変更しました。
プラットフォームターゲット変更のデメリットとして、前バージョンのアプリケーション設定を引き継ぐことが出来なくなります。ここはユーザー側で最初から入力し直してもらう手筈になりました。
テスト作業も終えて、ユーザー側にも導入しました。
Office 64bit
1年以上経ってからユーザー側から、印刷しようとしたらエラーになるとの報告がありました。
どうも新しいPCに導入したようです、Windows 10 64bit + Office 365 64bit の環境となっているとのこと。
エラーのログはまだもらっていなかったのですが、Office 64bitの環境でテストしていなかったことに気が付いたのです。
会社から提供されているPCは Office 32bit版であり、開発やテストでもその環境でやっていたためです。
はたして、32bitアプリケーションから64bit版のAccessのレポートが使えるのだろうか?
using Access = Microsoft.Office.Interop.Access;
Microsoft.Office.Interop.Access.ApplicationClass oAccess = null;
//レポートの印刷
oAccess = new Microsoft.Office.Interop.Access.ApplicationClass();
oAccess.OpenCurrentDatabase(MDBFileName, false)
oAccess.DoCmd.OpenReport(REPORT_NAME, Access.AcView.acViewNormal, null, null);
oAccess.CloseCurrentDatabase();
Imports Access = Microsoft.Office.Interop.Access
Dim oAccess As Microsoft.Office.Interop.Access.ApplicationClass = Nothing
'レポートの印刷
oAccess = New Microsoft.Office.Interop.Access.ApplicationClass()
oAccess.OpenCurrentDatabase(MDBFileName, False)
oAccess.DoCmd.OpenReport(REPORT_NAME, Access.AcView.acViewNormal, Nothing, Nothing)
oAccess.CloseCurrentDatabase()
今のところテスト環境はOffice 32bit版しかありません。
64bit環境からOffice 32bitの呼び出しが出来れば、その逆の32bit環境からOffice 64bitでも大丈夫ではないかと推測です。
テスト的にアプリケーションのプラットフォームターゲットをAnyCPUに変更、プロバイダー部分を「Provider=Microsoft.Jet.OLEDB.4.0」 → 「Provider=Microsoft.ACE.OLEDB.12.0」にして、「Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント」の64bit版をインストールして動かしてみました。
その結果、Accessのレポートが印刷できました。
その後、別途テスト環境用のPCを用意してもらい Office 365の32bitから64bitに入れ直しました。Office 365なら比較的簡単に変更が出来ました。
永続ライセンス版Officeを32bitから64bitに変更するには
その結果、32bitアプリ(x86)からでもAccessのレポートが印刷できました。
ユーザーからログをもらうと、Microsoft Accessがインストールされていたないためにエラーが発生していました。
System.Runtime.InteropServices.COMException (0x80040154): CLSID {73A4C9C1-D68D-11D0-98BF-00A0C90DC8D9} を含むコンポーネントの COM クラス ファクトリを取得中に、次のエラーが発生しました: 80040154
結論
プラットフォーム ターゲット | Office ビット | 動作 |
---|---|---|
AnyCPU(64bit) | Office 64bit | 問題なし |
AnyCPU(64bit) | Office 32bit | 問題なし |
x86 | Office 32bit | 問題なし |
x86 | Office 64bit | 問題なし |
最後に
最初は焦りましたがプログラムの修正はしないで済みました。
Excel操作だったら、オープンソースのNPOIやEEPlusやClosedXMLなどに変更すればいいですが、Accessだったのでどうしようもないです。
なんにしても、office 64bit環境によるテスト漏れがあったことは否めません。今度は気をつけましょう。