VS2005でMFCを使って開発しています。
現在COMを使って、Excelへのデータ書き出しを行ってしますが
Excelが入っている環境では問題なく動作するのですが
テストの為に、Excelが入っていない環境で動かすと上手く動作しない場合があります。
具体的にはCreateInstance("Excel.Application")するところで
エラーを返してくる場合とエラーも何も返さず、try〜catchを入れても
catchに入ってくれず、「クラスが登録されていません」というメッセージが出ます。
(Excelが入っていないとコンパイル出来ないため、テストは別マシンでメッセージボックスを
入れながら調べています。)
try {
AfxMessageBox("CreateInstance直前"); <−このメッセージ直後、「クラスが登録〜」が出る
hr = excel.CreateInstance("Excel.Application");
_com_error err(hr);
AfxMessageBox(err.ErrorMessage()); <−このメッセージすら出ない
if(hr!=S_OK){
return;
}
}
catch (_com_error& e) { <− catch (...)これでも駄目でした
e;
AfxMessageBox(e.ErrorMessage()); <−このメッセージも出ない
}
CreateInstance()でExcelの有無を判定することは不可能なのでしょうか?
また、その場合、Excelが入っているか確認するにはどうしたら良いのでしょうか?
調べてはみたのですが、FindExecutable()とかレジストリを見るとか載っていましたが
コレが良いという、決定的なものが見つからなかったので、よろしくお願いします。
結局、レジストリに「HKEY_CLASSES_ROOT\Excel.Application」のキーが
存在しない場合は、Excelがインストールされていないと判断することにしました。
Excelのバージョンが変わっても「HKEY_CLASSES_ROOT\Excel.Application」は
変わらずに存在し、その配下の「CurVer」に入っている値が変わるようなので
問題ないと思いました。
この方法が間違っているか否か分かる方がいましたら、よろしくお願いします。
HKEY_CLASSES_ROOT\Excel.Application\CurVerに「Excel.Application.9」が入っている
そこからHKEY_CLASSES_ROOT\Excel.Application.9を読みにいく?
ExcelのEXE単独で消された場合は?
例外がキャッチできないのは当然です。スローしてないんですから。
CreateInstance は勝手に例外を投げませんから、自分で投げないといけませんが、
> _com_error err(hr);
これは _com_error クラスのインスタンスを作っているだけです。
_com_error 例外を投げたいなら、_com_raise_error( hr ); としなければなりません。
で、
> AfxMessageBox(err.ErrorMessage()); <−このメッセージすら出ない
とのことですが、このメッセージが出ていないことはどのように確認しましたか?
> 「クラスが登録されていません」というメッセージが出ます。
というメッセージは、実はここで出ているのではないですか?
> ExcelのEXE単独で消された場合は?
ユーザが Program Files \ Microsoft Office フォルダから exe ファイルを消してしまった場合、ですか?
非現実的な想定だと思いますが、CreateInstance を呼び出した時点で修復インストールが走ってくれたりするのでしょうかね?
回答ありがとうございます。
>ExcelのEXE単独で消された場合は?
イレギュラーなパターンを突き詰めていくとキリが無いですし
レジストリと実行ファイルとの整合性もチェックした方が良いのでしょうが
今回は、ただ1つだけのレジストリ情報を信じてみることにしました。
>> 「クラスが登録されていません」というメッセージが出ます。
>というメッセージは、実はここで出ているのではないですか?
す、すいません、確かにそうだったかもしれません。
いや恐らくそうだと思います。それだと色々とつじつまが合いますし
ということは、S_OK以外の値が返ってきてreturnしていたのかも
しれませんね。
お恥ずかしい。。。
ちょっとソースを戻して実験してみたいと思います。
ありがとうございます。
お騒がせしました。
やはり、自分で入れたメッセージボックスの内容をずっと変なメッセージだと
思って調べていたようです。
ソースを元に戻し、CreateInstance()の戻り値で判断するように直しました。
今回はデバッグの有り難味を感じた一件でした。
ありがとうございます。
>非現実的な想定だと思いますが、CreateInstance を呼び出した時点で修復イン
>ストールが走ってくれたりするのでしょうかね?
勇気が無いので、自分は試しませんが…w
へそ曲がりユーザによってプログラム自体が消されない保証が無い為、
思いつく範囲でイレギュラーを提示してみました。
Windows 自体さえ、kernel32.dll が消されたときのことまで想定して作ってないんじゃないかと思います。
何より、通常のアプリは管理者権限で動かすべきではないので、消される心配はありません。
管理者がへそ曲がりだったら保証はできませんけど:P
ツイート | ![]() |