【问题标题】:Microsoft Office Interop Timing OutMicrosoft Office 互操作超时
【发布时间】:2013-07-23 12:07:14
【问题描述】:

我正在使用一个 C# 程序,该程序利用 Microsoft Office 互操作,使您能够以编程方式使用 Microsoft Word、Excel 和 PowerPoint。

我遇到的一个不幸的方面是,程序有时会弹出一个对话框,暂停代码。例如,如果代码突然无法保存在您期望能够保存的位置,这可能会发生这种情况,这意味着即使该问题稍后得到修复,您的整个程序也可能会暂停。

还有很多其他情况可能会出现额外的对话框。

所以我的意图是为此实现某种超时机制,从而我可以终止 Interop 实例,而不是让我的整个程序被捆绑。谁能建议一种方法来做到这一点?目前它将 Interop 调用包装在 System.Action 中并在给定时间后中止该线程,但我想知道是否有更好的方法。

【问题讨论】:

  • 我过去做过这样的事情。唯一要做的就是实际阅读您正在自动化的 VBA 代码,并对其进行测试,以便您知道对话框出现的时间和位置以及原因。然后你可以围绕它进行编程。相信我,从长远来看,它会让您的生活更轻松!
  • 另外,Office Interop 的设计初衷不是在无人看管的情况下使用,其想法是您的最终用户会看到这些对话框并与它们进行适当的交互。如果您想要无人值守的办公自动化,您可以查看 OpenXML。

标签: c# ms-office office-interop


【解决方案1】:

您可以通过实现 OLE 消息过滤器来做到这一点。详情请见this answer

【讨论】:

    【解决方案2】:

    很多人不建议杀掉进程;看 How to properly clean up Excel interop objectsUnderstanding Garbage Collection in .net

    这是我用来终止我创建的 Excel 实例的代码。您将需要对其进行一些重构以满足您的需求。您将看到如何使用 Excel 提供的窗口句柄获取进程 ID。我想这个过程对于 Word 或 Powerpoint 来说是一样的。

    'http://msdn.microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx
    <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
        ByRef lpdwProcessId As Integer) As Integer
    End Function
    
    Sub Work()
    
        'declare process; will be used later to attach the Excel process
        Dim XLProc As Process
    
        'start the application using late binding
        Dim xlApp As Object = CreateObject("Excel.Application")
    
        'or use early binding
        'Dim xlApp As Microsoft.Office.Interop.Excel
    
        'get the window handle
        Dim xlHWND As Integer = xlApp.hwnd
    
        'this will have the process ID after call to GetWindowThreadProcessId
        Dim ProcIdXL As Integer = 0
    
        'get the process ID
        GetWindowThreadProcessId(xlHWND, ProcIdXL)
    
        'get the process
        XLProc = Process.GetProcessById(ProcIdXL)
    
    
        'do some work with Excel here using xlApp
    
        'be sure to save and close all workbooks when done
    
        'release all objects used (except xlApp) using NAR(x)
    
    
        'Quit Excel 
        xlApp.quit()
    
        'Release
        NAR(xlApp)
    
        'Do garbage collection to release the COM pointers
        'http://support.microsoft.com/kb/317109
        GC.Collect()
        GC.WaitForPendingFinalizers()
    
        'I prefer to have two parachutes when dealing with the Excel process
        'this is the last answer if garbage collection were to fail
        If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then
            XLProc.Kill()
        End If
    End Sub
    
    Private Sub NAR(ByVal o As Object)
        'http://support.microsoft.com/kb/317109
        Try
            While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
            End While
        Catch
        Finally
            o = Nothing
        End Try
    End Sub
    

    【讨论】:

      猜你喜欢
      • 2013-06-09
      • 2011-08-23
      • 2010-11-17
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多