QA@IT

CreateObject使用時に想定外の遅延が発生

14048 PV

環境
 Visual Studio 2003
 VB.net
 Microsoft Office Excel 2003

exe起動しDBより吸い上げたデータを元にExcelファイル出力を
行うアプリケーション開発を行っています。
その中で、

Dim objXls as Object
objXls = CreateObject("Excel.Application")

このような処理を行っているのですが、
Windows XPではこの処理では特に躓く事無く通過しますが、
Windows 7では10秒近く遅延が発生します。
処理としては正しく動作します。

この処理は、

Dim objXls as New Microsoft.Office.Interop.Excel.Application

に変更することでWindows 7でもWindows XPとほぼ同等の処理時間に
することが出来ましたが、何故遅くなってしまうのか具体的な理由が知りたいです。

ご存知の方いらっしゃいましたら、宜しくお願いいたします。


2013/08/09 更新
この事象について、広く発生すると思っていたのですが
検索しても同様の不具合が出ているような記事をまったく見つけられないので、
こちらのアプリに何らかの問題があり、今回は工数も無いので
原因の特定はしない(出来ない)というところを着地点にしようと思います。

連絡して頂いた方々、本当に有難う御座いました。


2013/08/12 更新
再現する不具合ということが判明しました。
(詳細は下を読んで下さい。)

Windows7 + .Net Framework1.1構成は限りなく少数かと思いますが、
この不具合はExcelファイルを直接編集する処理は勿論ですが、
そのExcelを一時ファイルとしてBookの操作を行っていたり、
或いはそのファイルを用いた帳票出力を行う処理がある場合は対処が必要になります。

大量ファイル出力等で通常でも出力までに遅延がある場合は気が付き辛いですが
1秒2秒程度で完了する処理ではその動作遅延が顕著(15秒程度遅くなる)ですので、
必ず少量のデータでテストする事をお勧め致します。
(私はテスト時に偶然大量データでテストしていてこれに気が付きませんでした。)

  • 私のWin7 x64 + Office 2010 x86 の環境ではどちらも特に変わらないんですが、初回だけでなく毎回遅いんですか? -
  • 毎回遅いです。
    約100台程ある業務のPCでも同様の遅延が確認されているようなので、
    私のPC特有の事象ではないことは確認しています。
    ちなみにWindows7は32bitです。
    -
  • やってみる価値がありそうなのは、ビルド時にターゲットCPUをx86にしてみるか、新しいバージョンの.NETでビルドし直すかでしょうね。 -
  • レスありがとうございます。
    Visual Studio 2003なので、ターゲットCPUはx86固定で変更は出来ない(と思っています)ので、そちらは問題無いかと思います。
    他環境でのテストも試してみたいのですが、何ぶんインストールの許可が下りないので手詰まり状態です。
    -
  • たしかにターゲットは変更できませんね。ちなみにWin7のOfficeのバージョンも2003ですか? -
  • Windows7のOfficeは2010を使用しています。ですので、microsoft.office.interop.excel.dllは14となります。 -
  • 再現しました。回答に追記しました。 -
  • 対策も追記しました。 -

回答

環境作って試してみました。
結論から言えばこの環境では特にそんなことはなかったですね。
ウィルススキャンなどによりCOMラッパー作成に時間がかかっているのか…謎ですね。

  • 環境1
    Windows XP SP3 32bit (入れたて、Windows Updateは特にしてない)
    Visual Studio 2003 SP1
    .NET 1.1 (1.1.4322)
    .NET 2以降 未インストール
    Officeなし (Create Objectが遅いかどうかしか試さなかったので)

  • 環境2
    Window 7 SP1 32bit (入れたて、Windows Updateは特にしてない)
    .NET 2.0 SP2
    .NET 3.0 SP2
    .NET 3.5 SP1
    Office 2010

どちらもVMware Player上で、2コアCPU 2GBメモリです。仮想ディスクはSATA HDD上にあります
(SSDの恩恵は受けてません)。なので特別速いという事もないと思います。

以下のコードをXPでReleaseビルドし、exeをWin7のローカルドライブにコピーして、ボタンを連打。
初回こそ多少ロードの時間はあるが 2回目以降は 1秒以内に返ってきました。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim objXls As Object
        objXls = CreateObject("Excel.Application")
        objXls.Visible = True

        objXls = Nothing

    End Sub

ちなみにWindows7のVBSやOffice VBAからCreateObjectする分には速いんでしょうか?
こっちはCOM ラッパーじゃないので速くても不思議ではないですが。


8/12 追記

再現しました。
上記の環境2に対して .NET Framework 1.1および SP1をインストールした場合たしかに毎回遅くなります。
今再起動中ですが、再起動しても同じでしょう。

今起きたばかりなので対策はまだわかりません(し、とりあえずクローズされたみたいなので自分用に調べてなんかあれば提示してみますが放置しても構いません)。

ちなみに Win7で .NET1.1 をインストールするのはサポート外だった気がします。


追記

イベントログみると、なぜかOfficeインストーラが走っているので待たされているのはそれですね。
→ .NET 1.1用の相互運用アセンブリをインストールしようとして失敗しているようですね。


原因

原因はおそらく
http://msdn.microsoft.com/ja-jp/library/vstudio/kh3965hw.aspx
で(.NET2.0より古くない~の記述とPIAの話であるので)

対策

対策は以下のようなアプリケーション構成ファイル(App.Config)を作成し、強制的に .NET 2.0 で実行すれば速度は改善しました。
この策を採用できるかどうかは .NET 1.1をインストールしないといけなかった理由によります。
対象のアプリケーションが .NET 2.0モードでは何かが動かないので Windows 7に .NET 1.1を入れている場合、この策はとれないかもしれませんね。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <startup>
      <supportedRuntime version="v2.0.50727"/>
   </startup>
</configuration>

ちなみにバージョン文字列に指定すべき数字は

.NET Framework 1.0: 「v1.0.3705」
.NET Framework 1.1: 「v1.1.4322」
.NET Framework 2.0、3.0、および 3.5: 「v2.0.50727」
.NET Framework 4 および 4.5: 「v4.0」

です。

http://msdn.microsoft.com/ja-jp/library/jj152935.aspx

編集 履歴 (6)
  • すみません。大変お手数でしたでしょう...。
    環境2にほぼ全てのwindows update + Framework1.1をインストールしているものが当方の動作環境(に限りなく近い物)となります。
    -
  • Office(Excel)側でのマクロとして実行した場合は、①Office2003でCreateObjectを含んだマクロ実行 ②Office2010でCreateObjectを含んだマクロ実行(拡張子xls) ③Office2010でCreateObjectを含んだマクロ実行(拡張子xlsx)この3つのパターンで試行してみたところ、全てのパターンに於いて遅延はありませんでした。 -
  • 何か想定していない組み合わせで、CreateObjectをcallする際のコストが高くなるのかな...程度の認識で今回は閉じようと思います。一応回避策もあるので、この記事が同様の事象が発生した人の助けになればと...。ありがとうございました。 -
  • ありがとうございます。やはりそういった(サポート外構成による)不具合でしたか...。サポート外なのはわかった上で、今回は時間も無く人員も用意出来ないのでお茶を濁す感じでの動作検証途中でした。 -
  • おそらく、.Net Framework 2.0でも当方のアプリの動作には問題無いと思うのですが、既に1.1での動作検証パターンの半分以上を終えてしまっていて、再度同様の検証を行うことが難しいので、今回はdllの追加を行い処理を変更する形で回避することにします。 -
  • flied_onionさん、何度もありがとうございました。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。