DOBON.NET DOBON.NETプログラミング掲示板過去ログ

AxWebBrowserでのEXCELのプロセス解放について

環境/言語:[Win 2000 Pro VB.NET 2003]
分類:[.NET]

いつもおせわになります。

今VB.NET(2003)にてAXWebBrowserを用いてEXCEL
を表示させるプログラムを作成しています。

下記コードにてEXCELを表示
AxWebBrowser.Navigate("excelのファイルパス")

上記コードにてexcelの表示が出来、その際にプロセスに
EXCELのプロセスが出来ているのですがこの解放方法が
わかりません。普通にEXCELを使用する場合の分は
ネットなどですぐ調べがつくのですがこの方法に
関しては調べてもみつけることが出来ませんでした。

どのようにプロセスを解放したらよいのでしょう?
わかる方がおられましたら宜しくお願いします。
> どのようにプロセスを解放したらよいのでしょう?

できないし、必要ないのでは?
■No18422に返信(渋木宏明(ひどり)さんの記事)
>>どのようにプロセスを解放したらよいのでしょう?
>
> できないし、必要ないのでは?
>

渋木さんお返事ありがとうございます。

プロセスを解放したい理由としてはAというファイルを
最初指定のパスにあるかどうか確認してあれば削除して
サーバーにあるファイルを取得する。なければサーバー
から取得することとなっているのですが、最初に実行
した時には取得してきたEXCELファイルを表示すること
が出きるのですが2度目に実行しようとした場合ファイル
を削除する部分でアボートしてしまいます。
エラー内容としては他のプロセスで使用されているという
エラーとなります。 プログラムを終了させる時には
プロセスを解放してやりたいのですがこのパターンでは
無理なのでしょうか?
よい代替策でもいいのでわかれば教えて下さい。
宜しくお願いします。
> プロセスを解放してやりたいのですがこのパターンでは
> 無理なのでしょうか?

厳しいですね。

IE が、履歴にそのページを持っている間は EXCEL のインスタンスも保持してるはずです。

> よい代替策でもいいのでわかれば教えて下さい。

ファイルサーバ上のパスを与えてしまってますよね?

それを止めるしか無いです。
> IE が、履歴にそのページを持っている間は EXCEL のインスタンスも保持してるはずです。

試したわけではありませんが...
セッション履歴に保持されているのが原因でしたら,
ITravelLogStgインターフェイスを取得して履歴を削除したらダメでしょうかね。
2006/12/05(Tue) 06:39:24 編集(投稿者)

> セッション履歴に保持されているのが原因でしたら,
> ITravelLogStgインターフェイスを取得して履歴を削除したらダメでしょうかね。

それだと「誰かが見てる間」の状況については改善されないですね。
またまたお返事ありがとうございます。

自分なりに色々調べたのですがなかなかいい物がみつからなかったの
ですが一つ気になる記事をみつけました。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=20026&forum=7

これはパワーポイントの場合なのですがちょっとまねて

Private m_excel_b As Excel.Workbook
Private m_excel_s As Excel.Sheets
Private m_excel_ws As Excel.Worksheet

Me.m_excel_b = CType(GaiWebBrowser.Document, Excel.Workbook)
Me.m_excel_s = Me.m_excel_b.Sheets
Me.m_excel_ws = Me.m_excel_s.Item(1)

Me.m_excel_b = Nothing
Me.m_excel_s = Nothing
Me.m_excel_ws = Nothing

こんな感じでやってみたのですがEXCELのプロセスは解放
されませんでした。やっぱりこれより上位のapplication
などをnothingとしていないからかな?とかは思ったのですが

引き続き調査してみます。

宜しくお願いします。
■No18433に返信(こうさんの記事)
> またまたお返事ありがとうございます。
>
> 自分なりに色々調べたのですがなかなかいい物がみつからなかったの
> ですが一つ気になる記事をみつけました。
>
> http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=20026&forum=7
>
> これはパワーポイントの場合なのですがちょっとまねて
>
> Private m_excel_b As Excel.Workbook
> Private m_excel_s As Excel.Sheets
> Private m_excel_ws As Excel.Worksheet
>
> Me.m_excel_b = CType(GaiWebBrowser.Document, Excel.Workbook)
> Me.m_excel_s = Me.m_excel_b.Sheets
> Me.m_excel_ws = Me.m_excel_s.Item(1)
>
> Me.m_excel_b = Nothing
> Me.m_excel_s = Nothing
> Me.m_excel_ws = Nothing
>
> こんな感じでやってみたのですがEXCELのプロセスは解放
> されませんでした。やっぱりこれより上位のapplication
> などをnothingとしていないからかな?とかは思ったのですが
>
> 引き続き調査してみます。
>
> 宜しくお願いします。

@ITを見ておきながら、なぜ「ReleaseComObject」についてのスレッドを発見できないのかと小一時間問い詰めたいです。
@ITだと某氏の投稿によって、しょっちゅう見かけるんですけどね。
はいこーんさんお返事ありとごうございます。

記述不足で申し訳なかったのですが

ComObjectRelease(Me.m_excel_b)
ComObjectRelease(Me.m_excel_s)
ComObjectRelease(Me.m_excel_ws)

Private Sub ComObjectRelease(ByRef objCom As Object)
'明示的に COM オブジェクトへの参照を解放
Try
If Not objCom Is Nothing AndAlso System.Runtime.InteropServices. _
Marshal.IsComObject(objCom) Then
Dim I As Integer
Do
I = System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
Loop Until I <= 0
End If
Catch
Finally
'参照を解除する
objCom = Nothing
End Try
End Sub

上記のコードも試していたのですがEXCELのプロセスは解放
されませんでした。それでNOTHINGとしてみたのですがこれ
もだめでした(説明不足で申し訳ありませんでした。)

解放するものがたりないのでしょうか?
> 解放するものがたりないのでしょうか?

それ以前に、物凄くキケンなことやってることを理解していますか?
渋木さん何度もお返事ありがとうございます。

> それ以前に、物凄くキケンなことやってることを理解していますか?

すいませんあまりわかっていません。解放してるからメモリか何かに
不都合を与えるのかな?位にしか想像がつきませんでした。

基本的にAxWebBrowserで表示したEXCELのプロセスは解放すること
が出来ないのであれば一度AxWebBrowserで開いたEXCELファイルは
削除したり移動したり出来ず(再起動orマスクマネージャーでプロ
セスを強制終了する場合を除き)、また開く事も出来ないような状態
になっているのですがそれは回避は出来ないのであれば基本的には
AxWebBrowserでExcelを開くべきではないのででしょうか??
こんにちは、某氏ですw

■No18437に返信(こうさんの記事)
> Do
>     I = System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
> Loop Until I <= 0

参照カウントは自分で管理すべきものですから、
ここで、すべて参照カウントをデクリメントするのはおかしいと思います。

> Finally

をつけるべきところも、変だと思いますね。
とりあえず、このあたりをご参照ください。

 COM オブジェクトの参照カウントを解放する
 http://jeanne.wankuma.com/tips/programing/releasecom.html

 C#, VB.NET で Excel が終了しない 
 http://blogs.wankuma.com/jeanne/archive/2005/12/20/20102.aspx

# ところで、この件は当初の AxWebBrowser と関係があるのでしょうか...?
# すべての返信を眺めているわけでないので、流れがわかっていません。
>>それ以前に、物凄くキケンなことやってることを理解していますか?
>
> すいませんあまりわかっていません。解放してるからメモリか何かに
> 不都合を与えるのかな?位にしか想像がつきませんでした。

重大な障害になる危険があります。
IE が保持している Excel の参照を横から割っていって、無理くり参照カウントを0にしようとしてるんですから。

ブラウザコントロールは、誰かが Excel の参照を解放したことに気づきませんから、然るべき時が来れば自分が保持している「はず」の Excel の参照を解放しようと試みます。
しかし、そこにはもう Excel は居ないわけで、ブラウザコントロールが保持している参照は「無効参照」ということになります。

「無効参照」は要するに「出鱈目なポインタ」ですから、それに対して解放の操作を行えば最悪、ブラウザコントロールがクラッシュするはずです。

> AxWebBrowserでExcelを開くべきではないのででしょうか??

要件次第です。
ブラウザコントロールで Excel ブックを開く事それ自体が悪であるわけではありません。

ブラウザコントロールで Excel ブックを開いている最中に、同じ Excel ブックを編集したいような場合には不向きだということです。
> # ところで、この件は当初の AxWebBrowser と関係があるのでしょうか...?

Excel を自前でオートメーションしているのではなく、ブラウザコントロールに Navigate() して Excel ブックを表示させているようです。
■No18443に返信(渋木宏明(ひどり)さんの記事)
> Excel を自前でオートメーションしているのではなく、ブラウザコントロールに Navigate() して Excel ブックを表示させているようです。

なるほど、そこで横取りデクリメントということですか。
それは危険だ。(^-^;)
渋木さん、じゃんぬねっとさん
お返事ありがとうございます。
渋木さんの説明でいまやっている事が危険だということが
完全ではありませんがわかりました。

>Excel を自前でオートメーションしているのではなく、ブラウザコントロールに >Navigate() して Excel ブックを表示させているようです。

上記のようにあるのですがオートメーションで作成した
EXCELのオブジェクトをAxWebBrowserに表示する事は可能なのでしょうか?

わかれば教えて下さい。
宜しくお願いします。
> 上記のようにあるのですがオートメーションで作成した
> EXCELのオブジェクトをAxWebBrowserに表示する事は可能なのでしょうか?

できません。
渋木さんまたまた解答ありがとうございます。

調べていてわかったことと、今まで返事をよんできずいたことがありました。

自分もAxWebBrowserを初めて使用するのでわからなかったのですが

通常下記コードを記述することによって
AxWebBrowser1.Navigate("C:\Book1.xls")
コントロールにExcelが表示されプロセスにはEXCEL.EXEが生成され
てAxwebBrowserのあるフォームを閉じるとExcel.EXEのプロセスが
なくなる。(画面を閉じなくてもAxWebBrowser.Navigate("about:blank")と
してやることでファイルを扱う事が可能)

が正常の動きだと思うのですが下記条件で実行した場合動きが
変わってきます。

画面A(ログイン画面)からAxWebBrowserがある画面Bをshowdialogで
開きます。

画面Aのログインボタンクリック時
Dim 画面B As 画面B
画面B = New 画面B
画面B.ShowDialog()

そして画面BのAxWebBrowserに
AxWebBrowser1.Navigate("C:\Book1.xls")
とした時に最初画面にExcelが表示されExcelのプロセス
が生成されるところまでは同様の動きをするのですが
なぜか画面Bを閉じても(画面Aも閉じても)Excelの
プロセスがきえません。タスクマネージャー参照
(AxWebBrowser.Navigate("about:blank")
とした後にファイルをさわろうとすると他のプロセスで使用されている
というエラーになる。)

自分は最初に後述の方のコーディングをしていたのでこれが
AxWebBrowserの正しい動きだと思っていたのですがどうやら
前述したほうが正しい動きのようなので自分が勘違いしていた
ようです。

なぜ他画面から生成された画面のEXCELのプロセスはプログラムを
終了しても解放されないのでしょうか??

何かわかればお願いします。
> なぜ他画面から生成された画面のEXCELのプロセスはプログラムを
> 終了しても解放されないのでしょうか??



> Dim 画面B As 画面B
> 画面B = New 画面B
> 画面B.ShowDialog()

の後に

画面B.Dispose()

が抜けているからでは?
あと

> 通常下記コードを記述することによって
> AxWebBrowser1.Navigate("C:\Book1.xls")
> コントロールにExcelが表示されプロセスにはEXCEL.EXEが生成され
> てAxwebBrowserのあるフォームを閉じるとExcel.EXEのプロセスが
> なくなる。(画面を閉じなくてもAxWebBrowser.Navigate("about:blank")と
> してやることでファイルを扱う事が可能)

が分かっているなら、ShowDialog() した時、FormClosing() で Navigate("about:blank") してみるとか。
渋木さん毎度お返事ありがとうございます。

画面をDisposeしても状況はかわりませんでしたが
違う方法で解決しました。

今AxWebBrowserにEXCELを表示させているのですがその際に
ツールバーなども表示した為下記記述を追加しています。

Dim oDocument as object

Private Sub GaiWebBrowser_NavigateComplete2(ByVal sender As System.Object, ByVal e As AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event) Handles GaiWebBrowser.NavigateComplete2
oDocument = e.pDisp.Document
With oDocument.Application.CommandBars("Standard")
.Position = 4 '[msoBarFloating]
.Visible = True
End With
GaiWebBrowser.ExecWB(SHDocVw.OLECMDID.OLECMDID_HIDETOOLBARS, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER)
End Sub

としているのですが oDocumentにAxWebBrowserの何かを
割り当てている??かよくわかりませんが
画面が閉じられる時に
oDocument = Nothingを追加して終了させたところ
プロセスからExcelのプロセスが消えました。
なぜ明示的に記述しなければ解放されないのかは
謎ですが(PG終了後にすべて解放されると思っていたので)
一応解決とします。

渋木さんホントにお世話になりました。
解決済み!
■No18462に返信(こうさんの記事)
> With oDocument.Application.CommandBars("Standard")
>     .Position = 4 '[msoBarFloating]
>     .Visible = True
> End With

どうも伝わっていないようです。
最初から読み直すことをお勧めします。
> 画面が閉じられる時に
> oDocument = Nothingを追加して終了させたところ
> プロセスからExcelのプロセスが消えました。

んー、どうしてそれで帳尻が合うんでしょうね?

.NET 的には、oDocument = Nothing で COM オブジェクトの参照カウントを減らすことは無いはずなんですが。

DOBON.NET | プログラミング道 | プログラミング掲示板