在Dispose上使用IPreviewHandler和Excel文件的RPC_E_SERVERFAULT

时间:2012-09-21 09:58:21

标签: vb.net pinvoke com-interop

我使用Brad Smith的实现在Winforms / VB.Net中实现了一个PreviewHandler控件。

但是,每当我的控件处理并且上次预览的文件是Excel文件时,我在调用IPreviewHandler.Unload()时会得到一个无法捕获的带有RPC_E_SERVERFAULT的ComException,并且我最终得到一个空闲的Excel32.exe进程(在当我尝试预览另一个Excel文件,直到我手动停止该过程时,它会挂起我的应用程序。)

我在Brad的文章评论中发现了一个解决方法,即挂钩所有者表单的FormClosing事件,并从那里卸载预览处理程序。但是,在注释中,作者在包含表单的代码中挂钩事件,而不是在控件中。

我发现挂钩到控件中的FormClosing事件的唯一方法是挂钩到ParentChanged事件,然后导航到顶部父窗口,直到找到窗体,然后从那里添加FormClosing处理程序。

但是,这并不适用于所有情况(例如,我的PreviewHandler控件嵌套在窗体之前创建的另一个控件中。)

那么有没有办法正确处理我的预览处理程序控件而不会得到令人讨厌的COMException,或者从控件中找到父表单的任何方法?

处理代码如下:

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
        UnloadPreviewHandler()
    Catch

    End Try

    GC.Collect()

    MyBase.Dispose(disposing)
End Sub

Private Sub UnloadPreviewHandler()
    If previewHandler IsNot Nothing Then
        Try
            ' This line throws the exception when UnloadPreviewHandler is called from Dispose method.
            previewHandler.Unload()
        Finally
            Marshal.FinalReleaseComObject(previewHandler)
            previewHandler = Nothing
        End Try
    End If

    If previewStream IsNot Nothing Then
        previewStream.Close()
        previewStream = Nothing
    End If

    If Not String.IsNullOrWhiteSpace(currentTempFile) Then
        Try
            IO.File.Delete(currentTempFile)
        Catch

        End Try
    End If
End Sub

编辑:正如评论建议的那样,我尝试了C4F实现(下载了套件并运行了PreviewHandlerHost示例)。它们的实现也会出现问题(在预览Excel或Word文件时关闭应用程序)。

0 个答案:

没有答案