Word遅延バインドで例外発生PCあり

タグの編集
投稿者 usako  (社会人) 投稿日時 2023/10/12 09:58:56
以前にVB2013で作成したツールでは、Wordファイルの操作を行うため、
以下のようにWordの遅延バインドを使用しています。

Dim oWord As Object = Nothing

Try
    oWord = GetObject(, "Word.Application")

Catch ex As Exception
    oWord = CreateObject("Word.Application")
End Try

'以下、処理および取得したCOMオブジェクト変数の解放 


ただ、このツールを使用している人から、Wordファイルの処理で
エラーが発生する、という連絡がありました。
例外が発生した時にその内容をログ出力するようにしていたので、
そのログ内容を見ると、以下のようでした。

・例外の種類:System.Exception: ActiveX コンポーネントを作成できません。
・例外の発生場所:CreateObject("Word.Application")の行

また、詳細を確認すると、以下の通りでした。

・あらかじめWordソフトを起動しておけば、エラーは発生しない。
 →おそらく、GetObject(, "Word.Application")でWord.Applicationが
  取得出来たため
・該当PCには元々はOffice2013が入っていたが、何らかの不具合があった
 (付帯的な内容は不明)とのことで、2013のサポートの問題もあり、
 Office2019(H&B)をインストールしたとのこと。
 この時にOffice2013は自動的にアンインストールされたとのこと。
 今回発生したエラーは、Office2019のインストール後に発生したとのこと。
・他のPCではこの問題は発生していないとのこと。

CreateObject("Word.Application")に失敗する原因として、
何が考えられますか?

また、現在遅延バインドを用いている理由は、様々なWordのバージョンに
対応できるようにするためなのですが、現在、Word2010以前のものは
対象外にしようと思っています。
その場合、遅延バインドより、Microsoft.Office.Interop.Wordの参照の方が
よいでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/10/12 11:27:13
インストールされた Office 2019 は、ストアアプリ版でしょうか、デスクトップアプリ版でしょうか。
ストアアプリ版の場合、オートメーション操作に制限があるため、
アンインストールして、デスクトップ版の Word をインストールし直してみてください。

https://s-ys.co.jp/faq/%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%BD%E3%83%95%E3%83%88%E3%82%AA%E3%83%95%E3%82%A3%E3%82%B9%EF%BC%882016%E3%80%812019%E3%81%AA%E3%81%A9%EF%BC%89%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88

https://answers.microsoft.com/ja-jp/msoffice/forum/all/office/956cb54d-5441-4233-b3de-c3dbefe00d26
投稿者 usako  (社会人) 投稿日時 2023/10/12 12:03:24
魔界の仮面弁士様、ありがとうございました。
エラーが出た人に確認してみます。

ところで、ストアアプリ版の場合でも、制限はあるものの、
Word.Applicationオブジェクトの取得は可能なのでしょうか?
(CreateObjectは使えないが、GetObjectは使える、等)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/10/12 14:30:39
> ところで、ストアアプリ版の場合でも、制限はあるものの、
> Word.Applicationオブジェクトの取得は可能なのでしょうか?
ストア版は使ったことが無いため、具体的なところはまったく知らないです。

とはいえ、ストアアプリでは動かなかったが、デスクトップ版に入れ替えたら動いた、
という事例はよく耳にしています。あるいは Excel を制御する各社のアプリでも、
「ストア版は非サポート」という事例が多いですね。

こうした実行環境依存性の問題があるので、文書ファイルの読み書きだけが
目的の場合は、Word や Excel を直接操作するのではなく、*.docx や *.xlsx を
直接読み書きできるライブラリを採用した方が便利かもしれません。


> (CreateObjectは使えないが、GetObjectは使える、等)
オートメーションによる起動をサポートしていないが、
Running Object Table(ROT)からの取得はできる…という事かも知れません。

似た話として、「Microsoft Access のランタイム版」においては、
CreateObject は使えないが、GetObject はできる、という仕様があります。

KB295179:Microsoft Access ランタイムだけがインストールされているコンピュータでオートメーションを使用するとランタイム エラーが発生する
https://bit.ly/3LYyJfn

アクセスランタイムで他のDBのフォームを開くと実行時エラーになる
https://answers.microsoft.com/ja-jp/msoffice/forum/all/%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%A9/942a64e3-3632-4080-b440-9d859caa5c4c

また、パスワード付き xls ファイルを ODBC 接続で読み書きしたい場合には、
「そのファイルを、あらかじめ Excel を開いておいた状態にする」ことで
アクセス可能になる…という話もありました。
投稿者 usako  (社会人) 投稿日時 2023/10/13 14:47:09
魔界の仮面弁士様、ありがとうございました。
色々と勉強になります。

なお、エラーが出た人のOfficeがストアアプリ版かどうかについては、
ちょっと旅に出た?とのことで、確認は来週になりそうです。
新しい情報が得られましたら、また報告します。
投稿者 usako  (社会人) 投稿日時 2023/10/13 15:41:58
先程、旅先の人から連絡ありました。
ストアアプリ版ではなく、デスクトップ版だそうです。

そのPCには元々Office2013が入っていたとのことで、
Office2019インストール時にはOffice2013は自動的にアンインストールさせられたとのことです。
この時に、Office2013の情報がレジストリ―か何かに残ってしまい、
Word2019のCreateObjectに失敗する、なんてことはあるのでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/10/13 22:40:11
複数バージョンがインストールされた場合、手順によっては HKEY_CLASSES_ROOT 上に
古い ProgID が残ってしまうことがありますね。
バージョン番号付きの ProgID を指定してみるのは如何でしょうか。
https://itecjapan.xsrv.jp/2020/02/10/createobjectexcel-application%E3%81%8C64%E3%83%93%E3%83%83%E3%83%88office%E7%92%B0%E5%A2%83%E3%81%A7%E3%81%AF%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%82%8B/
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/10/13 23:25:44
こんな記事も発見。.NET 向けでは無く VBA 向けの記事ですけれど。
こちらの記事だと、むしろバージョン番号無しの ProgID を使うべきとされていますが…現状は既にその実装なんですよね。
https://support.microsoft.com/ja-jp/topic/office-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%A8%E3%83%A9%E3%83%BC429%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%82%8B-b6070e15-ea78-4349-2751-72bdb5f186f7

あとは別案として、ProgID 指定では無く、CLSID 指定で起動してみる、とか。
(下記は Option Strict On でも動くように CallByName にしていますが、実行時バインディングな呼び出しでも構いません)

Dim oWord As Object = Activator.CreateInstance(Type.GetTypeFromCLSID(Guid.Parse("{000209FF-0000-0000-C000-000000000046}")))
CallByName(oWord, "Visible", CallType.LetTrue)
投稿者 usako  (社会人) 投稿日時 2023/10/14 12:34:41
魔界の仮面弁士様、いつもありがとうございます。
ご教示頂いたCLSID 指定を試してみたいと思います。
WordのCLSIDは{000209FF-0000-0000-C000-000000000046}なのですね。
今は手元に開発環境がないので、来週にでも自分の環境で試してみて、
その後、エラーの発生する人のPCでどうなるか、確認してみます。
投稿者 usako   (社会人) 投稿日時 2023/10/26 14:56:16
エラーが出た人がしばらく帰ってこれないとのことで、まだ確認できておりません。
確認できましたら改めて報告します。