- PR -

VB.NET AxWebBrowserを使ってPowerPointを表示 再読込みでエラー

1
投稿者投稿内容
makimaki
会議室デビュー日: 2004/10/06
投稿数: 4
投稿日時: 2005-03-23 15:24
いつもお世話になっております

VB.NETでWindowsアプリケーションを開発しております。
ユーザの希望でシステム内にPowerPointでの編集を取り入れるため「AxWebBrowser」
でPowerPointを使用しています。

<困っていること>
「AxWebBrowser」にPowerPointを表示することは出来るのですが、読み直しの処理でPowerPointにファイルが掴まれててファイルの上書きコピーに失敗してしまいます。

PowerPointからファイルが開放された事を検知できれば何とかなりそうですがやり方がわかりません。

<環境>
Windows 2000
VB.NET 2003

<要素>
VB.NET
Windowsアプリケーション
AxWebBrowser
PowerPoint

<処理の流れ>

@フォームのロード
 マスタのPPTファイルをコピーして別名とし「AxWebBrowser」に表示
    
           ↓

Aフォームの初期化
 A-1「AxWebBrowser」の表示を初期化する。
 A-2 マスタのPPTファイルをコピーして別名とし、「AxWebBrowser」に表示


Aで表示を初期化するまではエラーが起きないのですがファイルをコピーする際に下記エラーが発生してしまいます。

<エラー内容>
'System.IO.IOException' のハンドルされていない例外が WindowsApplication3.exe で発生しました。

追加情報 : プロセスはファイル "C:\Documents and Settings\hogehoge\デスクトップ\ppt151215.ppt" にアクセスできません。このファイルは別のプロセスが使用中です。


PowerPointがファイルを掴んでいるのはわかるのですが、うまく開放できていません。
またエラーの発生は起きたり起きなかったりしています。

※一旦、PowerPointのプロセスをKill方法ではうまくいくのですが、ユーザがシステムと平行してPowerPointを使う場合もあるとの事なので、なるべくKillしない方向ですすめたいと考えています。

<参考にしたサイトなど>

■[HOWTO] Visual Basic .NET で、WebBrowser コントロールを使用して Office ドキュメントを開く方法
ttp://support.microsoft.com/default.aspx?scid=kb;ja;304643

■[HOWTO] Visual Basic .NET でオートメーションを使用して PowerPoint プレゼンテーションの作成および表示を行う方法
ttp://support.microsoft.com/default.aspx?scid=kb;ja;303717

■Navigatgeのクリア
ttp://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=6911&forum=7&start=8



<コード>
Imports System.Text
Imports System.IO
Imports System.IO.Path


Private m_PPTFilePath As String 'PPTパス

'パワーポイント用
Private m_oPres As PowerPoint.Presentation
Private m_oSlide As PowerPoint.Slide

Private Const MAST_PPT_FOLDER As String = "C:\Documents and Settings\hogehoge\デスクトップ\"
Private Const MAST_PPT_FILE As String = "ppt"
Private Const MARK_PPT As String = ".ppt"


'@
'ロードイベント
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
'マスタファイルをコピー
m_PPTFilePath = Me.CopyMasterFile
'表示
AxWebBrowser1.Navigate(m_PPTFilePath)
End Sub

#Region "AxWebBrowser1_NavigateComplete2イベント"
Private Sub AxWebBrowser1_NavigateComplete2(ByVal sender As Object, _
ByVal e As AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event) _
Handles AxWebBrowser1.NavigateComplete2

Try
m_oPres = Nothing
'ブラウザで開いたドキュメントを格納。
Me.m_oPres = CType(AxWebBrowser1.Document, PowerPoint.Presentation)
'スライドのセット
Me.m_oSlide = m_oPres.Slides.Item(1)

Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
#End Region


'A-1
#Region "初期化(マスタファイルからの読み直し)"  

Private Sub MenuItem3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem3.Click
'リセット
AxWebBrowser1.Navigate("")
m_oPres = Nothing
m_oSlide = Nothing
'ガベッジコレクション
GC.Collect()

'マスタファイルをコピー
m_PPTFilePath = Me.CopyMasterFile
'表示
AxWebBrowser1.Navigate(m_PPTFilePath)
End Sub

#End Region

'A-2
#Region "PPTマスタファイルのコピー"
Private Function CopyMasterFile() As String
Try
'システム用のPowerPointのPathを作成
Dim FilePath As String = MAST_PPT_FOLDER + MAST_PPT_FILE + CStr(Format(Now, "HHmmss")) + MARK_PPT
'ファイルのコピー
File.Copy(MAST_PPT_FOLDER + MAST_PPT_FILE + MARK_PPT, FilePath, True)
'返り値を設定
CopyMasterFile = FilePath
Catch ex As Exception
Throw (ex)
End Try
End Function
#End Region
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2005-03-23 16:43
こんにちは。

提示されたコードだと、CopyMasterFile()メソッドが呼び出されるたびにコピー先ファイル名(別名)は変更されるので、「・・・このファイルは別のプロセスが使用中です。」というエラーは発生しないと思われるけど。。。

1秒間にMenuItem3が複数回クリックされれば、現象はでるけど尋ねたいのはそういうことではないですよね。
makimaki
会議室デビュー日: 2004/10/06
投稿数: 4
投稿日時: 2005-03-23 19:19
>noderaさん
早速の回答有難う御座います。

おっしゃられるとおり1秒間にMenuItem3が複数回クリックするとエラーになります。。

実はコピー先のファイル名を変更してるのは狗肉の策でして、本来はファイル名を変更しなくてもA-1のリセット処理でPPTファイルを開放したいと考えていますがうまくいきません。

'リセット
AxWebBrowser1.Navigate("")
m_oPres = Nothing
m_oSlide = Nothing
'ガベッジコレクション
GC.Collect()

リセット処理が足りないためかもしれません。
Sleepを入れてもうまくPowerPointから開放されない状態です。
いろいろ調べてるのですが、なかなかいい事例がなくて。。
もうすこし調べてます。


※非同期で動いているPowerPointに対してこういったコードを使用するのがそもそも誤りなのかもしれませんが。。
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2005-03-24 10:07
こんにちは。

原因は、WebBrowserがこの時点(MenuItem3_Click)では、パワーポイントのドキュメントを解放していないことです。AxWebBrowser1.Navigate("")としていますが、実際に解放されるのは、AxWebBrowser1_NavigateComplete2イベントが動作する直前でしょう。

次のようにすればとりあえずは、ファイル名が同じでもコピーできると思います。
(本番のコードでは、NavigateComplete2イベントの条件判断をもう少し工夫する必要があるかもしれませんが)
コード:

Private Sub AxWebBrowser1_NavigateComplete2(ByVal sender As Object,
ByVal e As AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event) Handles AxWebBrowser1.NavigateComplete2
Try
If (e.uRL = "http:///") Then
'マスタファイルをコピー
m_PPTFilePath = Me.CopyMasterFile
'表示
AxWebBrowser1.Navigate(m_PPTFilePath)
Else
m_oPres = Nothing
'ブラウザで開いたドキュメントを格納。
Me.m_oPres = CType(AxWebBrowser1.Document, PowerPoint.Presentation)
'スライドのセット
Me.m_oSlide = m_oPres.Slides.Item(1)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub

Private Sub MenuItem3_Click(ByVal sender As System.Object,
 ByVal e As System.EventArgs) Handles MenuItem3.Click
'リセット
AxWebBrowser1.Navigate("")
m_oPres = Nothing
m_oSlide = Nothing
End Sub



#読みにくくなったので編集

#クリアするのは、AxWebBrowser1.Navigate("about:blank")の方がよさそうだ。
#当然条件判断も、If (e.uRL = "about:blank") Thenに変わるけど。

[ メッセージ編集済み 編集者: nodera 編集日時 2005-03-24 10:08 ]

[ メッセージ編集済み 編集者: nodera 編集日時 2005-03-24 10:19 ]
makimaki
会議室デビュー日: 2004/10/06
投稿数: 4
投稿日時: 2005-03-25 09:49
>noderaさん

おはようございます。
サンプルソース有難う御座いました。
コードの方、サンプルに実装してみたところうまく動きました。

>原因は、WebBrowserがこの時点(MenuItem3_Click)では、パワーポイントのドキュメン
>トを解放していないことです。AxWebBrowser1.Navigate ("")としていますが、
>実際に解放されるのは、AxWebBrowser1_NavigateComplete2イベントが動作する直前で
>しょう。

はい、ドキュメントの開放がどうにもならず困っていたのですが、NavigateComplete2でもういちどNavigateを呼ぶという発想がなかったです。
(ボタンが二つ有ればなんとかなったのですが・・(苦笑))

PowerPointのプロセスをKillせずに平行してPowerPointも使用できました。
大変助かりました。有難う御座います。



1

スキルアップ/キャリアアップ(JOB@IT)